From fc99eb0214271ab3f0e2dddd7db44ffc1513b9a1 Mon Sep 17 00:00:00 2001 From: marco <marco@5a81b35b-ba03-0410-adc8-b2c5c5119f08> Date: Wed, 28 Jul 2010 13:19:10 +0000 Subject: [PATCH] added install command-line tool dialog a dialog pop-up the first time a user starts DNG on the Mac and asks if symlinks for the command-line tools should be created. git-svn-id: https://dng.biozentrum.unibas.ch/svn/openstructure/trunk@2595 5a81b35b-ba03-0410-adc8-b2c5c5119f08 --- modules/gui/pymod/CMakeLists.txt | 6 ++ modules/gui/pymod/dng/__init__.py | 0 modules/gui/pymod/dng/termuse.py | 70 ++++++++++++++++++++++ modules/gui/pymod/init_menubar.py | 7 ++- modules/gui/pymod/init_splash.py | 2 +- modules/gui/pymod/wrap_gui.cc | 9 ++- modules/gui/src/CMakeLists.txt | 14 ++++- modules/gui/src/admin.cc | 98 +++++++++++++++++++++++++++++++ modules/gui/src/admin.hh | 49 ++++++++++++++++ scripts/init.py | 9 ++- 10 files changed, 258 insertions(+), 6 deletions(-) create mode 100644 modules/gui/pymod/dng/__init__.py create mode 100644 modules/gui/pymod/dng/termuse.py create mode 100644 modules/gui/src/admin.cc create mode 100644 modules/gui/src/admin.hh diff --git a/modules/gui/pymod/CMakeLists.txt b/modules/gui/pymod/CMakeLists.txt index 2d36fa75b..d6ceebcff 100644 --- a/modules/gui/pymod/CMakeLists.txt +++ b/modules/gui/pymod/CMakeLists.txt @@ -84,8 +84,14 @@ set(OST_GUI_PYMOD_MODULES init_splash.py ) +set(OST_GUI_PYMOD_DNG_MODULES + __init__.py + termuse.py +) + pymod(NAME gui CPP ${OST_GUI_PYMOD_SOURCES} PY ${OST_GUI_SCENE_PYMOD_MODULES} IN_DIR scene + ${OST_GUI_PYMOD_DNG_MODULES} IN_DIR dng ${OST_GUI_PYMOD_MODULES}) set(PRESET_FILES diff --git a/modules/gui/pymod/dng/__init__.py b/modules/gui/pymod/dng/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/modules/gui/pymod/dng/termuse.py b/modules/gui/pymod/dng/termuse.py new file mode 100644 index 000000000..13341a0ca --- /dev/null +++ b/modules/gui/pymod/dng/termuse.py @@ -0,0 +1,70 @@ +from PyQt4.QtGui import * +from PyQt4.QtCore import * +from ost.gui import AdminRights +import ost +import os +#from ost.gui import AdminRights + +usage='''The DNG application bundle contains two shell commands ('ost' and 'dng') that lets you use the OpenStructure command-line interpreter and dng from the terminal. If you want to use these commands, it is recommended that a symbolic link is created. +''' +class TerminalUsageDialog(QDialog): + def __init__(self, parent=None): + QDialog.__init__(self, parent) + self.setWindowTitle('Enhanced Terminal Usage') + self.setFixedSize(QSize(480, 300)) + l=QVBoxLayout(self) + title=QLabel('Enhanced Terminal Usage') + font=title.font() + font.setPointSize(20) + title.setFont(font) + l.addWidget(title) + text=QLabel(usage) + l.addWidget(text) + l2=QHBoxLayout() + l2.addWidget(QLabel('If you proceed, the link will be created in: ')) + self.path_combo=QComboBox() + self.path_combo.setFixedWidth(150) + for path in os.getenv('PATH').split(':'): + if os.path.exists(os.path.expanduser(path)): + self.path_combo.addItem(path) + l2.addWidget(self.path_combo) + l.addLayout(l2) + l3=QHBoxLayout() + ab=QPushButton('Create Link') + ab.setDefault(True) + cb=QPushButton('Don\'t Create') + l3.addStretch(1) + l3.addWidget(cb, 0) + l3.addWidget(ab, 0) + l.addLayout(l3) + text.setWordWrap(True) + QObject.connect(cb, SIGNAL('clicked()'), self.reject) + QObject.connect(ab, SIGNAL('clicked()'), self.accept) + def GetSelectedPath(self): + return str(self.path_combo.currentText()) + +def _CreateLinks(bin_dir, sel_dir): + for bin in ('ost', 'dng',): + if os.path.exists(os.path.join(sel_dir, bin)): + os.unlink(os.path.join(sel_dir, bin)) + os.system('ln -s "%s" "%s"' % (os.path.join(bin_dir, bin), + os.path.join(sel_dir, bin))) +def InstallTerminalPrograms(): + """ + Installs symlinks to the 'ost' and 'dng' command line programs into a + user-specified directory in the path. + """ + term_use=TerminalUsageDialog() + if term_use.exec_(): + prefix=ost.GetPrefixPath() + bin_dir=os.path.join(prefix, 'bin') + sel_path=term_use.GetSelectedPath() + if not os.access(sel_path, os.W_OK): + admin_rights=AdminRights() + if admin_rights.Acquire(): + for bin in ('ost', 'dng'): + admin_rights.CreateLink(os.path.join(bin_dir, bin), + os.path.join(sel_path, bin)) + admin_rights.Release() + else: + _CreateLinks(bin_dir, sel_path) diff --git a/modules/gui/pymod/init_menubar.py b/modules/gui/pymod/init_menubar.py index d1c33cfae..ac5c23e23 100644 --- a/modules/gui/pymod/init_menubar.py +++ b/modules/gui/pymod/init_menubar.py @@ -28,7 +28,7 @@ from ost.gui import FileLoader from ost.gui.scene.file_loader import GenericLoader from ost.gui.scene.loader_manager_widget import LoaderManagerWidget from ost.gui.init_splash import _InitSplash - +from ost.gui.dng import termuse class InitMenuBar(QtCore.QObject): def __init__(self, menu_bar=None): QtCore.QObject.__init__(self, menu_bar) @@ -50,6 +50,11 @@ class InitMenuBar(QtCore.QObject): webpage.setShortcut('Ctrl+D') self.connect(webpage, QtCore.SIGNAL('triggered()'), self.OpenDocs) help.addAction(webpage) + if sys.platform=='darwin': + install_ctl=QtGui.QAction('Install Command Line Tool', self) + self.connect(install_ctl, QtCore.SIGNAL('triggered()'), + termuse.InstallTerminalPrograms) + help.addAction(install_ctl) about = QtGui.QAction('&About', self) about.setStatusTip('About') about.setShortcut('Ctrl+A') diff --git a/modules/gui/pymod/init_splash.py b/modules/gui/pymod/init_splash.py index 2941c858d..332636063 100644 --- a/modules/gui/pymod/init_splash.py +++ b/modules/gui/pymod/init_splash.py @@ -22,6 +22,6 @@ class SplashDialog(QtGui.QDialog): def _InitSplash(): splash = SplashDialog(gui.GostyApp.Instance().perspective.main_area.qobject) - splash.showNormal() + splash.exec_() #QtCore.QTimer.singleShot(30000, splash.close); diff --git a/modules/gui/pymod/wrap_gui.cc b/modules/gui/pymod/wrap_gui.cc index 53dffcc83..712d4ce4e 100644 --- a/modules/gui/pymod/wrap_gui.cc +++ b/modules/gui/pymod/wrap_gui.cc @@ -21,7 +21,7 @@ #include <boost/python.hpp> #include <QString> #include <ost/config.hh> - +#include <ost/gui/admin.hh> using namespace boost::python; void export_AlignmentView(); @@ -97,6 +97,7 @@ namespace { } +using namespace ost::gui; BOOST_PYTHON_MODULE(_gui) { @@ -131,4 +132,10 @@ BOOST_PYTHON_MODULE(_gui) export_overlay(); export_overlay_manager(); #endif + + class_<AdminRights>("AdminRights", init<>()) + .def("Acquire", &AdminRights::Acquire) + .def("Release", &AdminRights::Release) + .def("CreateLink", &AdminRights::CreateLink) + ; } diff --git a/modules/gui/src/CMakeLists.txt b/modules/gui/src/CMakeLists.txt index b4ba16d2d..9504b73d8 100644 --- a/modules/gui/src/CMakeLists.txt +++ b/modules/gui/src/CMakeLists.txt @@ -169,6 +169,7 @@ gl_canvas.hh gl_win.hh scene_menu.hh gosty_app.hh +admin.hh main.hh main_area.hh module_config.hh @@ -204,6 +205,7 @@ main_window.cc gl_win.cc scene_menu.cc widget.cc +admin.cc widget_pool.cc remote_site_loader.cc sequence_viewer/align_properties_painter.cc @@ -458,7 +460,9 @@ if (ENABLE_SPNAV) input/spnav_input.hh ) endif() - +if (APPLE) + set(ADDITIONAL_LIBRARIES "-framework Security") +endif() set(QT_USE_QTOPENGL 1) set(QT_USE_QTNETWORK 1) include(${QT_USE_FILE}) @@ -474,7 +478,13 @@ module(NAME gui SOURCES ${OST_GUI_MOCS} ${OST_GUI_SOURCES} ${OST_GUI_DATA_VIEWER_HEADERS} ${OST_GUI_HEADERS} DEPENDS_ON gfx io mol_alg seq_alg - LINK ${QT_LIBRARIES} ${PYTHON_LIBRARIES} ${BOOST_PYTHON_LIBRARIES} ${SPNAV_LIBRARIES}) + LINK ${QT_LIBRARIES} ${PYTHON_LIBRARIES} ${BOOST_PYTHON_LIBRARIES} + ${SPNAV_LIBRARIES}) + +if (ADDITIONAL_LIBRARIES) + target_link_libraries(ost_gui "${ADDITIONAL_LIBRARIES}") +endif() + include_directories(${PYTHON_INCLUDE_PATH}) qt4_add_resources(OST_QT_RESOURCE dngr.qrc) qt4_wrap_cpp(OST_GOSTY_MOC "gosty.hh") diff --git a/modules/gui/src/admin.cc b/modules/gui/src/admin.cc new file mode 100644 index 000000000..2b3de2da8 --- /dev/null +++ b/modules/gui/src/admin.cc @@ -0,0 +1,98 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// 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 3.0 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 "admin.hh" + +namespace ost { namespace gui { + +#if defined(__APPLE__) + +AdminRights::AdminRights(): auth_(NULL) +{ + +} +AdminRights::~AdminRights() +{ + this->Release(); +} + +bool AdminRights::Acquire() +{ + // Connect to Authorization Services. + if (AuthorizationCreate(NULL, NULL, 0, &auth_)!=noErr) { + return false; + } + + static const AuthorizationFlags kFlags = + kAuthorizationFlagInteractionAllowed + | kAuthorizationFlagExtendRights; + AuthorizationItem kActionRight = { "", 0, 0, 0 }; + AuthorizationRights kRights = { 1, &kActionRight }; + + assert(gAuthorization != NULL); + + // Request the application-specific right. + return noErr==AuthorizationCopyRights(auth_, &kRights, NULL, kFlags, NULL); +} + +void AdminRights::Release() +{ + if (auth_) { + AuthorizationFree(auth_, kAuthorizationFlagDestroyRights); + auth_=NULL; + } +} + +void AdminRights::CreateLink(const String& from, const String& to) +{ + static const char* minus_s="-s"; + // const_casts are gross, but at least that way we keep gcc happy + char* const args[]={ + const_cast<char*>(minus_s), + const_cast<char*>(from.c_str()), + const_cast<char*>(to.c_str()), + NULL + }; + AuthorizationExecuteWithPrivileges(auth_, "/bin/ln", + kAuthorizationFlagDefaults, + args, NULL); +} + +#else + +AdminRights::AdminRights() +{ } + +void AdminRights::CreateLink(const String& from, const String& to) +{ + +} +AdminRights::~AdminRights() +{ } + +bool AdminRights::Acquire() +{ } + +void AdminRights::Release() +{ } +#endif + + +}} + diff --git a/modules/gui/src/admin.hh b/modules/gui/src/admin.hh new file mode 100644 index 000000000..99e43e860 --- /dev/null +++ b/modules/gui/src/admin.hh @@ -0,0 +1,49 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// 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 3.0 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 OST_GUI_ADMIN_HH +#define OST_GUI_ADMIN_HH + +#include <ost/gui/module_config.hh> + +#if defined(__APPLE__) +#include <Security/Security.h> +#endif + +namespace ost { namespace gui { + + +class DLLEXPORT_OST_GUI AdminRights { +public: + AdminRights(); + ~AdminRights(); + + bool Acquire(); + + void CreateLink(const String& from, const String& to); + void Release(); +private: +#if defined(__APPLE__) + AuthorizationRef auth_; +#endif +}; + +}} + +#endif diff --git a/scripts/init.py b/scripts/init.py index df9341020..7d79e018f 100644 --- a/scripts/init.py +++ b/scripts/init.py @@ -18,7 +18,7 @@ from ost.gui.init_menubar import _InitMenuBar from ost.gui.init_spacenav import _InitSpaceNav from ost.gui.init_context_menu import _InitContextMenu from ost.gui.init_splash import _InitSplash - +from ost.gui.dng import termuse def _InitRuleBasedBuilder(): compound_lib_path=os.path.join(ost.GetSharedDataPath(), 'compounds.chemlib') if os.path.exists(compound_lib_path): @@ -56,6 +56,7 @@ def _InitPanels(app): return False return True + def _InitFrontEnd(): _CheckRestore() app=gui.GostyApp.Instance() @@ -64,6 +65,11 @@ def _InitFrontEnd(): _InitMenuBar(app) if not _InitPanels(app): _InitSplash() + if sys.platform=='darwin': + settings=QtCore.QSettings() + if not settings.value('install/clt', False).toBool(): + settings.setValue('install/clt', QtCore.QVariant(True)) + termuse.InstallTerminalPrograms() _InitSpaceNav(app) _InitContextMenu(app) main_area.AddPersistentWidget("3D Scene", "gl_win" , app.gl_win, int(QtCore.Qt.WindowMaximized)) @@ -72,6 +78,7 @@ def _InitFrontEnd(): for module_name in additional_modules: __import__(module_name) app.ProcessEvents() + _InitInspector(app) def _load_files(): -- GitLab