Merge pythonqt branch
This commit is contained in:
parent
095e5317cb
commit
4752f70809
@ -55,8 +55,9 @@ find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Core Gui Widgets LinguistTools S
|
|||||||
find_package( YAMLCPP 0.5.1 REQUIRED )
|
find_package( YAMLCPP 0.5.1 REQUIRED )
|
||||||
find_package( PolkitQt5-1 REQUIRED )
|
find_package( PolkitQt5-1 REQUIRED )
|
||||||
|
|
||||||
option( WITH_PYTHON "Enable Python modules support." ON )
|
option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON )
|
||||||
option( WITH_CRASHREPORTER "Build with CrashReporter" ON )
|
option( WITH_CRASHREPORTER "Build with CrashReporter" ON )
|
||||||
|
option( WITH_PYTHONQT "Enable next generation Python modules API (experimental, requires PythonQt)." OFF )
|
||||||
|
|
||||||
if( CMAKE_SYSTEM_PROCESSOR MATCHES "arm" OR NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libcrashreporter-qt/CMakeLists.txt" )
|
if( CMAKE_SYSTEM_PROCESSOR MATCHES "arm" OR NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libcrashreporter-qt/CMakeLists.txt" )
|
||||||
message( STATUS "Build of crashreporter disabled." )
|
message( STATUS "Build of crashreporter disabled." )
|
||||||
@ -84,11 +85,23 @@ if ( PYTHONLIBS_FOUND )
|
|||||||
FALSE "1.54.0"
|
FALSE "1.54.0"
|
||||||
"Boost.Python is used for interfacing with Calamares job modules written in Python 3."
|
"Boost.Python is used for interfacing with Calamares job modules written in Python 3."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
macro_optional_find_package( PythonQt )
|
||||||
|
macro_log_feature( PYTHONQT_FOUND
|
||||||
|
"PythonQt"
|
||||||
|
"A Python embedding solution for Qt applications."
|
||||||
|
"http://pythonqt.sourceforge.net"
|
||||||
|
FALSE "3.1"
|
||||||
|
"PythonQt is used for the Python modules API."
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if ( PYTHONLIBS_NOTFOUND OR NOT CALAMARES_BOOST_PYTHON3_FOUND )
|
if ( PYTHONLIBS_NOTFOUND OR NOT CALAMARES_BOOST_PYTHON3_FOUND )
|
||||||
set( WITH_PYTHON OFF )
|
set( WITH_PYTHON OFF )
|
||||||
endif()
|
endif()
|
||||||
|
if ( PYTHONLIBS_NOTFOUND OR NOT PYTHONQT_FOUND )
|
||||||
|
set( WITH_PYTHONQT OFF )
|
||||||
|
endif()
|
||||||
|
|
||||||
###
|
###
|
||||||
### Calamares application info
|
### Calamares application info
|
||||||
@ -167,8 +180,12 @@ add_subdirectory( src )
|
|||||||
macro_display_feature_log()
|
macro_display_feature_log()
|
||||||
|
|
||||||
if ( NOT WITH_PYTHON )
|
if ( NOT WITH_PYTHON )
|
||||||
message( "-- WARNING: Building Calamares without Python support. Python modules will not work.\n" )
|
message( "-- WARNING: Building Calamares without Python support. Legacy Python job modules will not work.\n" )
|
||||||
endif()
|
endif()
|
||||||
|
if ( NOT WITH_PYTHONQT )
|
||||||
|
message( "-- WARNING: Building Calamares without PythonQt support. Python modules will not work.\n" )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# Add all targets to the build-tree export set
|
# Add all targets to the build-tree export set
|
||||||
set( CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Calamares" CACHE PATH "Installation directory for CMake files" )
|
set( CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Calamares" CACHE PATH "Installation directory for CMake files" )
|
||||||
|
69
CMakeModules/FindPythonQt.cmake
Normal file
69
CMakeModules/FindPythonQt.cmake
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# Find PythonQt
|
||||||
|
#
|
||||||
|
# Sets PYTHONQT_FOUND, PYTHONQT_INCLUDE_DIR, PYTHONQT_LIBRARY, PYTHONQT_LIBRARIES
|
||||||
|
#
|
||||||
|
|
||||||
|
# Python is required
|
||||||
|
find_package(PythonLibs)
|
||||||
|
if(NOT PYTHONLIBS_FOUND)
|
||||||
|
message(FATAL_ERROR "error: Python is required to build PythonQt")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS "${PYTHONQT_INSTALL_DIR}")
|
||||||
|
find_path(PYTHONQT_INSTALL_DIR include/PythonQt/PythonQt.h DOC "Directory where PythonQt was installed.")
|
||||||
|
endif()
|
||||||
|
# XXX Since PythonQt 3.0 is not yet cmakeified, depending
|
||||||
|
# on how PythonQt is built, headers will not always be
|
||||||
|
# installed in "include/PythonQt". That is why "src"
|
||||||
|
# is added as an option. See [1] for more details.
|
||||||
|
# [1] https://github.com/commontk/CTK/pull/538#issuecomment-86106367
|
||||||
|
find_path(PYTHONQT_INCLUDE_DIR PythonQt.h
|
||||||
|
PATHS "${PYTHONQT_INSTALL_DIR}/include/PythonQt"
|
||||||
|
"${PYTHONQT_INSTALL_DIR}/src"
|
||||||
|
DOC "Path to the PythonQt include directory")
|
||||||
|
find_library(PYTHONQT_LIBRARY_RELEASE PythonQt PATHS "${PYTHONQT_INSTALL_DIR}/lib" DOC "The PythonQt library.")
|
||||||
|
find_library(PYTHONQT_LIBRARY_DEBUG NAMES PythonQt${CTK_CMAKE_DEBUG_POSTFIX} PythonQt${CMAKE_DEBUG_POSTFIX} PythonQt PATHS "${PYTHONQT_INSTALL_DIR}/lib" DOC "The PythonQt library.")
|
||||||
|
find_library(PYTHONQT_QTALL_LIBRARY_RELEASE PythonQt_QtAll PATHS "${PYTHONQT_INSTALL_DIR}/lib" DOC "Full Qt bindings for the PythonQt library.")
|
||||||
|
find_library(PYTHONQT_QTALL_LIBRARY_DEBUG NAMES PythonQt_QtAll${CTK_CMAKE_DEBUG_POSTFIX} PythonQt_QtAll${CMAKE_DEBUG_POSTFIX} PythonQt_QtAll PATHS "${PYTHONQT_INSTALL_DIR}/lib" DOC "Full Qt bindings for the PythonQt library.")
|
||||||
|
|
||||||
|
set(PYTHONQT_LIBRARY)
|
||||||
|
|
||||||
|
if(PYTHONQT_LIBRARY_RELEASE)
|
||||||
|
list(APPEND PYTHONQT_LIBRARY optimized ${PYTHONQT_LIBRARY_RELEASE})
|
||||||
|
endif()
|
||||||
|
if(PYTHONQT_LIBRARY_DEBUG)
|
||||||
|
list(APPEND PYTHONQT_LIBRARY debug ${PYTHONQT_LIBRARY_DEBUG})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(PYTHONQT_QTALL_LIBRARY)
|
||||||
|
if(PYTHONQT_QTALL_LIBRARY_RELEASE)
|
||||||
|
list(APPEND PYTHONQT_QTALL_LIBRARY optimized ${PYTHONQT_QTALL_LIBRARY_RELEASE})
|
||||||
|
endif()
|
||||||
|
if(PYTHONQT_QTALL_LIBRARY_DEBUG)
|
||||||
|
list(APPEND PYTHONQT_QTALL_LIBRARY debug ${PYTHONQT_QTALL_LIBRARY_DEBUG})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(PYTHONQT_INSTALL_DIR)
|
||||||
|
mark_as_advanced(PYTHONQT_INCLUDE_DIR)
|
||||||
|
mark_as_advanced(PYTHONQT_LIBRARY_RELEASE)
|
||||||
|
mark_as_advanced(PYTHONQT_LIBRARY_DEBUG)
|
||||||
|
mark_as_advanced(PYTHONQT_QTALL_LIBRARY_RELEASE)
|
||||||
|
mark_as_advanced(PYTHONQT_QTALL_LIBRARY_DEBUG)
|
||||||
|
|
||||||
|
# On linux, also find libutil
|
||||||
|
if(UNIX AND NOT APPLE)
|
||||||
|
find_library(PYTHONQT_LIBUTIL util)
|
||||||
|
mark_as_advanced(PYTHONQT_LIBUTIL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# All upper case _FOUND variable is maintained for backwards compatibility.
|
||||||
|
set(PYTHONQT_FOUND 0)
|
||||||
|
set(PythonQt_FOUND 0)
|
||||||
|
if(PYTHONQT_INCLUDE_DIR AND PYTHONQT_LIBRARY AND PYTHONQT_QTALL_LIBRARY)
|
||||||
|
# Currently CMake'ified PythonQt only supports building against a python Release build.
|
||||||
|
# This applies independently of CTK build type (Release, Debug, ...)
|
||||||
|
add_definitions(-DPYTHONQT_USE_RELEASE_PYTHON_FALLBACK)
|
||||||
|
set(PYTHONQT_FOUND 1)
|
||||||
|
set(PythonQt_FOUND ${PYTHONQT_FOUND})
|
||||||
|
set(PYTHONQT_LIBRARIES ${PYTHONQT_LIBRARY} ${PYTHONQT_LIBUTIL} ${PYTHONQT_QTALL_LIBRARY})
|
||||||
|
endif()
|
@ -58,6 +58,20 @@ if( WITH_PYTHON )
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if( WITH_PYTHONQT )
|
||||||
|
include_directories(${PYTHON_INCLUDE_DIRS})
|
||||||
|
link_directories(${PYTHON_LIBRARIES})
|
||||||
|
|
||||||
|
include_directories(${PYTHONQT_INCLUDE_DIR})
|
||||||
|
link_directories(${PYTHONQT_LIBRARY})
|
||||||
|
|
||||||
|
set( OPTIONAL_PRIVATE_LIBRARIES
|
||||||
|
${OPTIONAL_PRIVATE_LIBRARIES}
|
||||||
|
${PYTHON_LIBRARIES}
|
||||||
|
${PYTHONQT_LIBRARY}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
add_library( calamares SHARED ${libSources} )
|
add_library( calamares SHARED ${libSources} )
|
||||||
set_target_properties( calamares
|
set_target_properties( calamares
|
||||||
|
@ -11,5 +11,6 @@
|
|||||||
//cmakedefines for CMake variables (e.g. for optdepends) go here
|
//cmakedefines for CMake variables (e.g. for optdepends) go here
|
||||||
#cmakedefine WITH_PYTHON
|
#cmakedefine WITH_PYTHON
|
||||||
#cmakedefine WITH_CRASHREPORTER
|
#cmakedefine WITH_CRASHREPORTER
|
||||||
|
#cmakedefine WITH_PYTHONQT
|
||||||
|
|
||||||
#endif // CALAMARESCONFIG_H
|
#endif // CALAMARESCONFIG_H
|
||||||
|
@ -29,37 +29,33 @@ namespace Calamares {
|
|||||||
class DLLEXPORT JobResult
|
class DLLEXPORT JobResult
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
operator bool() const;
|
virtual ~JobResult() {}
|
||||||
|
|
||||||
QString message() const;
|
virtual operator bool() const;
|
||||||
void setMessage( const QString& message );
|
|
||||||
|
|
||||||
QString details() const;
|
virtual QString message() const;
|
||||||
void setDetails( const QString& details );
|
virtual void setMessage( const QString& message );
|
||||||
|
|
||||||
|
virtual QString details() const;
|
||||||
|
virtual void setDetails( const QString& details );
|
||||||
|
|
||||||
static JobResult ok();
|
static JobResult ok();
|
||||||
|
|
||||||
static JobResult error( const QString& message, const QString& details = QString() );
|
static JobResult error( const QString& message, const QString& details = QString() );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit JobResult( bool ok, const QString& message, const QString& details );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_ok;
|
bool m_ok;
|
||||||
QString m_message;
|
QString m_message;
|
||||||
QString m_details;
|
QString m_details;
|
||||||
|
|
||||||
JobResult( bool ok, const QString& message, const QString& details );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLLEXPORT Job : public QObject
|
class DLLEXPORT Job : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum State
|
|
||||||
{
|
|
||||||
Pending = 0,
|
|
||||||
Running,
|
|
||||||
Finished
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit Job( QObject* parent = nullptr );
|
explicit Job( QObject* parent = nullptr );
|
||||||
virtual ~Job();
|
virtual ~Job();
|
||||||
|
|
||||||
|
@ -189,7 +189,8 @@ Helper::Helper( QObject* parent )
|
|||||||
// Let's make extra sure we only call Py_Initialize once
|
// Let's make extra sure we only call Py_Initialize once
|
||||||
if ( !s_instance )
|
if ( !s_instance )
|
||||||
{
|
{
|
||||||
Py_Initialize();
|
if ( !Py_IsInitialized() )
|
||||||
|
Py_Initialize();
|
||||||
|
|
||||||
m_mainModule = bp::import( "__main__" );
|
m_mainModule = bp::import( "__main__" );
|
||||||
m_mainNamespace = m_mainModule.attr( "__dict__" );
|
m_mainNamespace = m_mainModule.attr( "__dict__" );
|
||||||
|
@ -39,6 +39,25 @@ if( WITH_PYTHON )
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if( WITH_PYTHONQT )
|
||||||
|
include_directories(${PYTHON_INCLUDE_DIRS})
|
||||||
|
include_directories(${PYTHONQT_INCLUDE_DIR})
|
||||||
|
|
||||||
|
list( APPEND ${CALAMARESUI_LIBRARY_TARGET}_SOURCES
|
||||||
|
modulesystem/PythonQtViewModule.cpp
|
||||||
|
utils/PythonQtUtils.cpp
|
||||||
|
viewpages/PythonQtJob.cpp
|
||||||
|
viewpages/PythonQtViewStep.cpp
|
||||||
|
viewpages/PythonQtGlobalStorageWrapper.cpp
|
||||||
|
viewpages/PythonQtUtilsWrapper.cpp
|
||||||
|
)
|
||||||
|
set( OPTIONAL_PRIVATE_LIBRARIES
|
||||||
|
${OPTIONAL_PRIVATE_LIBRARIES}
|
||||||
|
${PYTHON_LIBRARIES}
|
||||||
|
${PYTHONQT_LIBRARIES}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
calamares_add_library( ${CALAMARESUI_LIBRARY_TARGET}
|
calamares_add_library( ${CALAMARESUI_LIBRARY_TARGET}
|
||||||
SOURCES ${${CALAMARESUI_LIBRARY_TARGET}_SOURCES}
|
SOURCES ${${CALAMARESUI_LIBRARY_TARGET}_SOURCES}
|
||||||
UI ${${CALAMARESUI_LIBRARY_TARGET}_UI}
|
UI ${${CALAMARESUI_LIBRARY_TARGET}_UI}
|
||||||
@ -47,6 +66,7 @@ calamares_add_library( ${CALAMARESUI_LIBRARY_TARGET}
|
|||||||
yaml-cpp
|
yaml-cpp
|
||||||
Qt5::Svg
|
Qt5::Svg
|
||||||
Qt5::QuickWidgets
|
Qt5::QuickWidgets
|
||||||
|
${OPTIONAL_PRIVATE_LIBRARIES}
|
||||||
RESOURCES libcalamaresui.qrc
|
RESOURCES libcalamaresui.qrc
|
||||||
EXPORT CalamaresLibraryDepends
|
EXPORT CalamaresLibraryDepends
|
||||||
VERSION ${CALAMARES_VERSION_SHORT}
|
VERSION ${CALAMARES_VERSION_SHORT}
|
||||||
|
@ -39,7 +39,7 @@ CppJobModule::type() const
|
|||||||
Module::Interface
|
Module::Interface
|
||||||
CppJobModule::interface() const
|
CppJobModule::interface() const
|
||||||
{
|
{
|
||||||
return QtPlugin;
|
return QtPluginInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +31,10 @@
|
|||||||
#include "PythonJobModule.h"
|
#include "PythonJobModule.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_PYTHONQT
|
||||||
|
#include "PythonQtViewModule.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <yaml-cpp/yaml.h>
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@ -71,9 +75,18 @@ Module::fromDescriptor( const QVariantMap& moduleDescriptor,
|
|||||||
<< instanceId;
|
<< instanceId;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if ( typeString == "view" && intfString == "qtplugin" )
|
if ( typeString == "view" )
|
||||||
{
|
{
|
||||||
m = new ViewModule();
|
if ( intfString == "qtplugin" )
|
||||||
|
{
|
||||||
|
m = new ViewModule();
|
||||||
|
}
|
||||||
|
#ifdef WITH_PYTHONQT
|
||||||
|
else if ( intfString == "pythonqt" )
|
||||||
|
{
|
||||||
|
m = new PythonQtViewModule();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if ( typeString == "job" )
|
else if ( typeString == "job" )
|
||||||
{
|
{
|
||||||
@ -215,6 +228,38 @@ Module::location() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString
|
||||||
|
Module::typeString() const
|
||||||
|
{
|
||||||
|
switch ( type() )
|
||||||
|
{
|
||||||
|
case Job:
|
||||||
|
return "Job Module";
|
||||||
|
case View:
|
||||||
|
return "View Module";
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString
|
||||||
|
Module::interfaceString() const
|
||||||
|
{
|
||||||
|
switch ( interface() )
|
||||||
|
{
|
||||||
|
case ProcessInterface:
|
||||||
|
return "External process";
|
||||||
|
case PythonInterface:
|
||||||
|
return "Python (Boost.Python)";
|
||||||
|
case PythonQtInterface:
|
||||||
|
return "Python (experimental)";
|
||||||
|
case QtPluginInterface:
|
||||||
|
return "Qt Plugin";
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Module::isLoaded() const
|
Module::isLoaded() const
|
||||||
{
|
{
|
||||||
|
@ -48,9 +48,10 @@ public:
|
|||||||
|
|
||||||
enum Interface
|
enum Interface
|
||||||
{
|
{
|
||||||
QtPlugin,
|
QtPluginInterface,
|
||||||
Python,
|
PythonInterface,
|
||||||
Process
|
ProcessInterface,
|
||||||
|
PythonQtInterface
|
||||||
};
|
};
|
||||||
virtual ~Module();
|
virtual ~Module();
|
||||||
|
|
||||||
@ -65,7 +66,9 @@ public:
|
|||||||
virtual QStringList requiredModules() const;
|
virtual QStringList requiredModules() const;
|
||||||
virtual QString location() const final;
|
virtual QString location() const final;
|
||||||
virtual Type type() const = 0;
|
virtual Type type() const = 0;
|
||||||
|
virtual QString typeString() const;
|
||||||
virtual Interface interface() const = 0;
|
virtual Interface interface() const = 0;
|
||||||
|
virtual QString interfaceString() const;
|
||||||
|
|
||||||
virtual bool isLoaded() const;
|
virtual bool isLoaded() const;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ ProcessJobModule::type() const
|
|||||||
Module::Interface
|
Module::Interface
|
||||||
ProcessJobModule::interface() const
|
ProcessJobModule::interface() const
|
||||||
{
|
{
|
||||||
return Process;
|
return ProcessInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ PythonJobModule::type() const
|
|||||||
Module::Interface
|
Module::Interface
|
||||||
PythonJobModule::interface() const
|
PythonJobModule::interface() const
|
||||||
{
|
{
|
||||||
return Python;
|
return PythonInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
203
src/libcalamaresui/modulesystem/PythonQtViewModule.cpp
Normal file
203
src/libcalamaresui/modulesystem/PythonQtViewModule.cpp
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Calamares 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PythonQtViewModule.h"
|
||||||
|
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
#include "viewpages/ViewStep.h"
|
||||||
|
#include "viewpages/PythonQtViewStep.h"
|
||||||
|
#include "ViewManager.h"
|
||||||
|
#include "CalamaresConfig.h"
|
||||||
|
#include "viewpages/PythonQtGlobalStorageWrapper.h"
|
||||||
|
#include "viewpages/PythonQtUtilsWrapper.h"
|
||||||
|
#include "GlobalStorage.h"
|
||||||
|
#include "JobQueue.h"
|
||||||
|
|
||||||
|
#include <PythonQt.h>
|
||||||
|
#include <extensions/PythonQt_QtAll/PythonQt_QtAll.h>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
|
|
||||||
|
static QPointer< GlobalStorage > s_gs = nullptr;
|
||||||
|
static QPointer< Utils > s_utils = nullptr;
|
||||||
|
|
||||||
|
namespace Calamares {
|
||||||
|
|
||||||
|
Module::Type
|
||||||
|
PythonQtViewModule::type() const
|
||||||
|
{
|
||||||
|
return View;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Module::Interface
|
||||||
|
PythonQtViewModule::interface() const
|
||||||
|
{
|
||||||
|
return PythonQtInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PythonQtViewModule::loadSelf()
|
||||||
|
{
|
||||||
|
if ( !m_scriptFileName.isEmpty() )
|
||||||
|
{
|
||||||
|
if ( PythonQt::self() == nullptr )
|
||||||
|
{
|
||||||
|
if ( Py_IsInitialized() )
|
||||||
|
PythonQt::init( PythonQt::IgnoreSiteModule |
|
||||||
|
PythonQt::RedirectStdOut |
|
||||||
|
PythonQt::PythonAlreadyInitialized );
|
||||||
|
else
|
||||||
|
PythonQt::init();
|
||||||
|
|
||||||
|
PythonQt_QtAll::init();
|
||||||
|
cDebug() << "Initializing PythonQt bindings."
|
||||||
|
<< "This should only happen once.";
|
||||||
|
|
||||||
|
//TODO: register classes here into the PythonQt environment, like this:
|
||||||
|
//PythonQt::self()->registerClass( &PythonQtViewStep::staticMetaObject,
|
||||||
|
// "calamares" );
|
||||||
|
|
||||||
|
// We only do the following to force PythonQt to create a submodule
|
||||||
|
// "calamares" for us to put our static objects in
|
||||||
|
PythonQt::self()->registerClass( &::GlobalStorage::staticMetaObject,
|
||||||
|
"calamares" );
|
||||||
|
|
||||||
|
// Get a PythonQtObjectPtr to the PythonQt.calamares submodule
|
||||||
|
PythonQtObjectPtr pqtm = PythonQt::priv()->pythonQtModule();
|
||||||
|
PythonQtObjectPtr cala = PythonQt::self()->lookupObject( pqtm, "calamares" );
|
||||||
|
|
||||||
|
// Prepare GlobalStorage object, in module PythonQt.calamares
|
||||||
|
if ( !s_gs )
|
||||||
|
s_gs = new ::GlobalStorage( Calamares::JobQueue::instance()->globalStorage() );
|
||||||
|
cala.addObject( "global_storage", s_gs );
|
||||||
|
|
||||||
|
// Prepare Utils object, in module PythonQt.calamares
|
||||||
|
if ( !s_utils )
|
||||||
|
s_utils = new ::Utils( Calamares::JobQueue::instance()->globalStorage() );
|
||||||
|
cala.addObject( "utils", s_utils );
|
||||||
|
|
||||||
|
// Basic stdout/stderr handling
|
||||||
|
QObject::connect( PythonQt::self(), &PythonQt::pythonStdOut,
|
||||||
|
[]( const QString& message )
|
||||||
|
{
|
||||||
|
cDebug() << "PythonQt OUT>" << message;
|
||||||
|
} );
|
||||||
|
QObject::connect( PythonQt::self(), &PythonQt::pythonStdErr,
|
||||||
|
[]( const QString& message )
|
||||||
|
{
|
||||||
|
cDebug() << "PythonQt ERR>" << message;
|
||||||
|
} );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir workingDir( m_workingPath );
|
||||||
|
if ( !workingDir.exists() )
|
||||||
|
{
|
||||||
|
cDebug() << "Invalid working directory"
|
||||||
|
<< m_workingPath
|
||||||
|
<< "for module"
|
||||||
|
<< name();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString fullPath = workingDir.absoluteFilePath( m_scriptFileName );
|
||||||
|
QFileInfo scriptFileInfo( fullPath );
|
||||||
|
if ( !scriptFileInfo.isReadable() )
|
||||||
|
{
|
||||||
|
cDebug() << "Invalid main script file path"
|
||||||
|
<< fullPath
|
||||||
|
<< "for module"
|
||||||
|
<< name();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct empty Python module with the given name
|
||||||
|
PythonQtObjectPtr cxt =
|
||||||
|
PythonQt::self()->
|
||||||
|
createModuleFromScript( name() );
|
||||||
|
if ( cxt.isNull() )
|
||||||
|
{
|
||||||
|
cDebug() << "Cannot load PythonQt context from file"
|
||||||
|
<< fullPath
|
||||||
|
<< "for module"
|
||||||
|
<< name();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString calamares_module_annotation =
|
||||||
|
"_calamares_module_typename = 'foo'\n"
|
||||||
|
"def calamares_module(viewmodule_type):\n"
|
||||||
|
" global _calamares_module_typename\n"
|
||||||
|
" _calamares_module_typename = viewmodule_type.__name__\n"
|
||||||
|
" return viewmodule_type\n";
|
||||||
|
|
||||||
|
// Load in the decorator
|
||||||
|
PythonQt::self()->evalScript( cxt, calamares_module_annotation );
|
||||||
|
|
||||||
|
// Load the module
|
||||||
|
PythonQt::self()->evalFile( cxt, fullPath );
|
||||||
|
|
||||||
|
m_viewStep = new PythonQtViewStep( cxt );
|
||||||
|
|
||||||
|
cDebug() << "PythonQtViewModule loading self for instance" << instanceKey()
|
||||||
|
<< "\nPythonQtViewModule at address" << this
|
||||||
|
<< "\nViewStep at address" << m_viewStep;
|
||||||
|
|
||||||
|
m_viewStep->setModuleInstanceKey( instanceKey() );
|
||||||
|
m_viewStep->setConfigurationMap( m_configurationMap );
|
||||||
|
ViewManager::instance()->addViewStep( m_viewStep );
|
||||||
|
m_loaded = true;
|
||||||
|
cDebug() << "PythonQtViewModule" << instanceKey() << "loading complete.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QList< job_ptr >
|
||||||
|
PythonQtViewModule::jobs() const
|
||||||
|
{
|
||||||
|
return m_viewStep->jobs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PythonQtViewModule::initFrom( const QVariantMap& moduleDescriptor )
|
||||||
|
{
|
||||||
|
Module::initFrom( moduleDescriptor );
|
||||||
|
QDir directory( location() );
|
||||||
|
m_workingPath = directory.absolutePath();
|
||||||
|
|
||||||
|
if ( !moduleDescriptor.value( "script" ).toString().isEmpty() )
|
||||||
|
{
|
||||||
|
m_scriptFileName = moduleDescriptor.value( "script" ).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PythonQtViewModule::PythonQtViewModule()
|
||||||
|
: Module()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PythonQtViewModule::~PythonQtViewModule()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Calamares
|
54
src/libcalamaresui/modulesystem/PythonQtViewModule.h
Normal file
54
src/libcalamaresui/modulesystem/PythonQtViewModule.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Calamares 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CALAMARES_PYTHONQTVIEWMODULE_H
|
||||||
|
#define CALAMARES_PYTHONQTVIEWMODULE_H
|
||||||
|
|
||||||
|
#include "UiDllMacro.h"
|
||||||
|
#include "Module.h"
|
||||||
|
|
||||||
|
namespace Calamares {
|
||||||
|
|
||||||
|
class ViewStep;
|
||||||
|
|
||||||
|
class UIDLLEXPORT PythonQtViewModule : public Module
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Type type() const override;
|
||||||
|
Interface interface() const override;
|
||||||
|
|
||||||
|
void loadSelf() override;
|
||||||
|
QList< job_ptr > jobs() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void initFrom( const QVariantMap& moduleDescriptor ) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class Module; //so only the superclass can instantiate
|
||||||
|
explicit PythonQtViewModule();
|
||||||
|
virtual ~PythonQtViewModule();
|
||||||
|
|
||||||
|
ViewStep* m_viewStep = nullptr;
|
||||||
|
|
||||||
|
QString m_scriptFileName;
|
||||||
|
QString m_workingPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Calamares
|
||||||
|
|
||||||
|
#endif // CALAMARES_PYTHONQTVIEWMODULE_H
|
@ -39,7 +39,7 @@ ViewModule::type() const
|
|||||||
Module::Interface
|
Module::Interface
|
||||||
ViewModule::interface() const
|
ViewModule::interface() const
|
||||||
{
|
{
|
||||||
return QtPlugin;
|
return QtPluginInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,6 +26,12 @@
|
|||||||
#include "modulesystem/ModuleManager.h"
|
#include "modulesystem/ModuleManager.h"
|
||||||
#include "modulesystem/Module.h"
|
#include "modulesystem/Module.h"
|
||||||
|
|
||||||
|
#ifdef WITH_PYTHONQT
|
||||||
|
#include <gui/PythonQtScriptingConsole.h>
|
||||||
|
#include "ViewManager.h"
|
||||||
|
#include "viewpages/PythonQtViewStep.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QSplitter>
|
#include <QSplitter>
|
||||||
#include <QStringListModel>
|
#include <QStringListModel>
|
||||||
@ -68,11 +74,6 @@ DebugWindow::DebugWindow()
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
// Modules page
|
// Modules page
|
||||||
QSplitter* splitter = new QSplitter( modulesTab );
|
|
||||||
modulesTab->layout()->addWidget( splitter );
|
|
||||||
splitter->addWidget( modulesListView );
|
|
||||||
splitter->addWidget( moduleConfigView );
|
|
||||||
|
|
||||||
QStringListModel* modulesModel = new QStringListModel( ModuleManager::instance()->loadedInstanceKeys() );
|
QStringListModel* modulesModel = new QStringListModel( ModuleManager::instance()->loadedInstanceKeys() );
|
||||||
modulesListView->setModel( modulesModel );
|
modulesListView->setModel( modulesModel );
|
||||||
modulesListView->setSelectionMode( QAbstractItemView::SingleSelection );
|
modulesListView->setSelectionMode( QAbstractItemView::SingleSelection );
|
||||||
@ -80,8 +81,76 @@ DebugWindow::DebugWindow()
|
|||||||
QJsonModel* moduleConfigModel = new QJsonModel( this );
|
QJsonModel* moduleConfigModel = new QJsonModel( this );
|
||||||
moduleConfigView->setModel( moduleConfigModel );
|
moduleConfigView->setModel( moduleConfigModel );
|
||||||
|
|
||||||
|
#ifdef WITH_PYTHONQT
|
||||||
|
QPushButton* pythonConsoleButton = new QPushButton;
|
||||||
|
pythonConsoleButton->setText( "Attach Python console" );
|
||||||
|
modulesVerticalLayout->insertWidget( 1, pythonConsoleButton );
|
||||||
|
pythonConsoleButton->hide();
|
||||||
|
|
||||||
|
QObject::connect( pythonConsoleButton, &QPushButton::clicked,
|
||||||
|
this, [ this, moduleConfigModel ]
|
||||||
|
{
|
||||||
|
QString moduleName = modulesListView->currentIndex().data().toString();
|
||||||
|
Module* module = ModuleManager::instance()->moduleInstance( moduleName );
|
||||||
|
if ( module->interface() != Module::PythonQtInterface ||
|
||||||
|
module->type() != Module::View )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for ( ViewStep* step : ViewManager::instance()->viewSteps() )
|
||||||
|
{
|
||||||
|
if ( step->moduleInstanceKey() == module->instanceKey() )
|
||||||
|
{
|
||||||
|
PythonQtViewStep* pqvs =
|
||||||
|
qobject_cast< PythonQtViewStep* >( step );
|
||||||
|
if ( pqvs )
|
||||||
|
{
|
||||||
|
QWidget* consoleWindow = new QWidget;
|
||||||
|
|
||||||
|
QWidget* console = pqvs->createScriptingConsole();
|
||||||
|
console->setParent( consoleWindow );
|
||||||
|
|
||||||
|
QVBoxLayout* layout = new QVBoxLayout;
|
||||||
|
consoleWindow->setLayout( layout );
|
||||||
|
layout->addWidget( console );
|
||||||
|
|
||||||
|
QHBoxLayout* bottomLayout = new QHBoxLayout;
|
||||||
|
layout->addLayout( bottomLayout );
|
||||||
|
|
||||||
|
QLabel* bottomLabel = new QLabel( consoleWindow );
|
||||||
|
bottomLayout->addWidget( bottomLabel );
|
||||||
|
QString line =
|
||||||
|
QString( "Module: <font color=\"#008000\"><code>%1</code></font><br/>"
|
||||||
|
"Python class: <font color=\"#008000\"><code>%2</code></font>" )
|
||||||
|
.arg( module->instanceKey() )
|
||||||
|
.arg( console->property( "classname" ).toString() );
|
||||||
|
bottomLabel->setText( line );
|
||||||
|
|
||||||
|
QPushButton* closeButton = new QPushButton( consoleWindow );
|
||||||
|
closeButton->setText( "&Close" );
|
||||||
|
QObject::connect( closeButton, &QPushButton::clicked,
|
||||||
|
[ consoleWindow ]
|
||||||
|
{
|
||||||
|
consoleWindow->close();
|
||||||
|
} );
|
||||||
|
bottomLayout->addWidget( closeButton );
|
||||||
|
bottomLabel->setSizePolicy( QSizePolicy::Expanding,
|
||||||
|
QSizePolicy::Preferred );
|
||||||
|
|
||||||
|
consoleWindow->setParent( this );
|
||||||
|
consoleWindow->setWindowFlags( Qt::Window );
|
||||||
|
consoleWindow->setWindowTitle( "Calamares Python console" );
|
||||||
|
consoleWindow->setAttribute( Qt::WA_DeleteOnClose, true );
|
||||||
|
consoleWindow->showNormal();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
connect( modulesListView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
connect( modulesListView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||||
this, [ this, moduleConfigModel ]
|
this, [ this, moduleConfigModel, pythonConsoleButton ]
|
||||||
{
|
{
|
||||||
QString moduleName = modulesListView->currentIndex().data().toString();
|
QString moduleName = modulesListView->currentIndex().data().toString();
|
||||||
Module* module = ModuleManager::instance()->moduleInstance( moduleName );
|
Module* module = ModuleManager::instance()->moduleInstance( moduleName );
|
||||||
@ -89,6 +158,13 @@ DebugWindow::DebugWindow()
|
|||||||
{
|
{
|
||||||
moduleConfigModel->loadJson( QJsonDocument::fromVariant( module->configurationMap() ).toJson() );
|
moduleConfigModel->loadJson( QJsonDocument::fromVariant( module->configurationMap() ).toJson() );
|
||||||
moduleConfigView->expandAll();
|
moduleConfigView->expandAll();
|
||||||
|
moduleTypeLabel->setText( module->typeString() );
|
||||||
|
moduleInterfaceLabel->setText( module->interfaceString() );
|
||||||
|
#ifdef WITH_PYTHONQT
|
||||||
|
pythonConsoleButton->setVisible(
|
||||||
|
module->interface() == Module::PythonQtInterface &&
|
||||||
|
module->type() == Module::View );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>632</width>
|
<width>962</width>
|
||||||
<height>497</height>
|
<height>651</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -17,7 +17,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="globalStorageTab">
|
<widget class="QWidget" name="globalStorageTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
@ -48,7 +48,43 @@
|
|||||||
<widget class="QListView" name="modulesListView"/>
|
<widget class="QListView" name="modulesListView"/>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTreeView" name="moduleConfigView"/>
|
<layout class="QVBoxLayout" name="modulesVerticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="moduleTypeLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>none</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Interface:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="moduleInterfaceLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>none</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeView" name="moduleConfigView"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
44
src/libcalamaresui/utils/PythonQtUtils.cpp
Normal file
44
src/libcalamaresui/utils/PythonQtUtils.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Calamares 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PythonQtUtils.h"
|
||||||
|
|
||||||
|
namespace CalamaresUtils
|
||||||
|
{
|
||||||
|
|
||||||
|
QVariant
|
||||||
|
lookupAndCall( PyObject* object,
|
||||||
|
const QStringList& candidateNames,
|
||||||
|
const QVariantList& args,
|
||||||
|
const QVariantMap& kwargs )
|
||||||
|
{
|
||||||
|
Q_ASSERT( object );
|
||||||
|
Q_ASSERT( !candidateNames.isEmpty() );
|
||||||
|
|
||||||
|
for ( const QString& name : candidateNames )
|
||||||
|
{
|
||||||
|
PythonQtObjectPtr callable = PythonQt::self()->lookupCallable( object, name );
|
||||||
|
if ( callable )
|
||||||
|
return callable.call( args, kwargs );
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we haven't found a callable with the given names, we force an error:
|
||||||
|
return PythonQt::self()->call( object, candidateNames.first(), args, kwargs );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
src/libcalamaresui/utils/PythonQtUtils.h
Normal file
38
src/libcalamaresui/utils/PythonQtUtils.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Calamares 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PYTHONQTUTILS_H
|
||||||
|
#define PYTHONQTUTILS_H
|
||||||
|
|
||||||
|
#include <PythonQt.h>
|
||||||
|
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
|
||||||
|
namespace CalamaresUtils
|
||||||
|
{
|
||||||
|
//NOTE: when running this, it is assumed that Python is initialized and
|
||||||
|
// PythonQt::self() is valid.
|
||||||
|
QVariant lookupAndCall( PyObject* object,
|
||||||
|
const QStringList& candidateNames,
|
||||||
|
const QVariantList& args = QVariantList(),
|
||||||
|
const QVariantMap& kwargs = QVariantMap() );
|
||||||
|
|
||||||
|
} //ns
|
||||||
|
|
||||||
|
#endif // PYTHONQTUTILS_H
|
@ -0,0 +1,69 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Calamares 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PythonQtGlobalStorageWrapper.h"
|
||||||
|
|
||||||
|
#include "GlobalStorage.h"
|
||||||
|
|
||||||
|
|
||||||
|
GlobalStorage::GlobalStorage( Calamares::GlobalStorage* gs )
|
||||||
|
: QObject( gs )
|
||||||
|
, m_gs( gs )
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
GlobalStorage::contains( const QString& key ) const
|
||||||
|
{
|
||||||
|
return m_gs->contains( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
GlobalStorage::count() const
|
||||||
|
{
|
||||||
|
return m_gs->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GlobalStorage::insert( const QString& key, const QVariant& value )
|
||||||
|
{
|
||||||
|
m_gs->insert( key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QStringList
|
||||||
|
GlobalStorage::keys() const
|
||||||
|
{
|
||||||
|
return m_gs->keys();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
GlobalStorage::remove( const QString& key )
|
||||||
|
{
|
||||||
|
return m_gs->remove( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVariant
|
||||||
|
GlobalStorage::value( const QString& key ) const
|
||||||
|
{
|
||||||
|
return m_gs->value( key );
|
||||||
|
}
|
55
src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.h
Normal file
55
src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Calamares 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PYTHONQTGLOBALSTORAGEWRAPPER_H
|
||||||
|
#define PYTHONQTGLOBALSTORAGEWRAPPER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace Calamares
|
||||||
|
{
|
||||||
|
class GlobalStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This GlobalStorage class is a namespace-free wrapper for
|
||||||
|
* Calamares::GlobalStorage. This is unfortunately a necessity
|
||||||
|
* because PythonQt doesn't like namespaces.
|
||||||
|
*/
|
||||||
|
class GlobalStorage : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit GlobalStorage( Calamares::GlobalStorage* gs );
|
||||||
|
virtual ~GlobalStorage() {}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
bool contains( const QString& key ) const;
|
||||||
|
int count() const;
|
||||||
|
void insert( const QString& key, const QVariant& value );
|
||||||
|
QStringList keys() const;
|
||||||
|
int remove( const QString& key );
|
||||||
|
QVariant value( const QString& key ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Calamares::GlobalStorage* m_gs;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PYTHONQTGLOBALSTORAGEWRAPPER_H
|
77
src/libcalamaresui/viewpages/PythonQtJob.cpp
Normal file
77
src/libcalamaresui/viewpages/PythonQtJob.cpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Calamares 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PythonQtJob.h"
|
||||||
|
|
||||||
|
#include "utils/PythonQtUtils.h"
|
||||||
|
|
||||||
|
PythonQtJob::PythonQtJob( PythonQtObjectPtr cxt,
|
||||||
|
PythonQtObjectPtr pyJob,
|
||||||
|
QObject* parent )
|
||||||
|
: Calamares::Job( parent )
|
||||||
|
, m_cxt( cxt )
|
||||||
|
, m_pyJob( pyJob )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString
|
||||||
|
PythonQtJob::prettyName() const
|
||||||
|
{
|
||||||
|
return CalamaresUtils::lookupAndCall( m_pyJob,
|
||||||
|
{ "prettyName",
|
||||||
|
"prettyname",
|
||||||
|
"pretty_name" } ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString
|
||||||
|
PythonQtJob::prettyDescription() const
|
||||||
|
{
|
||||||
|
return CalamaresUtils::lookupAndCall( m_pyJob,
|
||||||
|
{ "prettyDescription",
|
||||||
|
"prettydescription",
|
||||||
|
"pretty_description" } ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString
|
||||||
|
PythonQtJob::prettyStatusMessage() const
|
||||||
|
{
|
||||||
|
return CalamaresUtils::lookupAndCall( m_pyJob,
|
||||||
|
{ "prettyStatusMessage",
|
||||||
|
"prettystatusmessage",
|
||||||
|
"pretty_status_message" } ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Calamares::JobResult
|
||||||
|
PythonQtJob::exec()
|
||||||
|
{
|
||||||
|
QVariant response = m_pyJob.call( "exec" );
|
||||||
|
if ( response.isNull() )
|
||||||
|
return Calamares::JobResult::ok();
|
||||||
|
|
||||||
|
QVariantMap map = response.toMap();
|
||||||
|
if ( map.isEmpty() || map.value( "ok" ).toBool() )
|
||||||
|
return Calamares::JobResult::ok();
|
||||||
|
|
||||||
|
return Calamares::JobResult::error( map.value( "message" ).toString(),
|
||||||
|
map.value( "details" ).toString() );
|
||||||
|
}
|
65
src/libcalamaresui/viewpages/PythonQtJob.h
Normal file
65
src/libcalamaresui/viewpages/PythonQtJob.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Calamares 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PYTHONQTJOB_H
|
||||||
|
#define PYTHONQTJOB_H
|
||||||
|
|
||||||
|
#include "Job.h"
|
||||||
|
|
||||||
|
#include <PythonQt.h>
|
||||||
|
|
||||||
|
namespace Calamares
|
||||||
|
{
|
||||||
|
class PythonQtViewStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PythonQtJobResult : public QObject, public Calamares::JobResult
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit PythonQtJobResult( bool ok,
|
||||||
|
const QString& message,
|
||||||
|
const QString& details )
|
||||||
|
: QObject( nullptr )
|
||||||
|
, Calamares::JobResult( ok, message, details )
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PythonQtJob : public Calamares::Job
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
virtual ~PythonQtJob() {}
|
||||||
|
|
||||||
|
QString prettyName() const override;
|
||||||
|
QString prettyDescription() const override;
|
||||||
|
QString prettyStatusMessage() const override;
|
||||||
|
Calamares::JobResult exec() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit PythonQtJob( PythonQtObjectPtr cxt,
|
||||||
|
PythonQtObjectPtr pyJob,
|
||||||
|
QObject* parent = nullptr );
|
||||||
|
friend class Calamares::PythonQtViewStep; // only this one can call the ctor
|
||||||
|
|
||||||
|
PythonQtObjectPtr m_cxt;
|
||||||
|
PythonQtObjectPtr m_pyJob;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PYTHONQTJOB_H
|
146
src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp
Normal file
146
src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Calamares 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PythonQtUtilsWrapper.h"
|
||||||
|
|
||||||
|
#include "utils/CalamaresUtilsSystem.h"
|
||||||
|
#include "utils/CalamaresUtils.h"
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
|
#include <PythonQt.h>
|
||||||
|
|
||||||
|
|
||||||
|
Utils::Utils(QObject* parent)
|
||||||
|
: QObject( parent )
|
||||||
|
, m_exceptionCxt( PythonQt::self()->createUniqueModule() )
|
||||||
|
{
|
||||||
|
PythonQt::self()->evalScript( m_exceptionCxt, "import subprocess" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Utils::debug(const QString& s) const
|
||||||
|
{
|
||||||
|
cDebug() << "PythonQt DBG>" << s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Utils::mount( const QString& device_path,
|
||||||
|
const QString& mount_point,
|
||||||
|
const QString& filesystem_name,
|
||||||
|
const QString& options ) const
|
||||||
|
{
|
||||||
|
return CalamaresUtils::System::instance()->
|
||||||
|
mount( device_path, mount_point, filesystem_name, options );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Utils::target_env_call( const QString& command,
|
||||||
|
const QString& stdin,
|
||||||
|
int timeout ) const
|
||||||
|
{
|
||||||
|
return CalamaresUtils::System::instance()->
|
||||||
|
targetEnvCall( command, QString(), stdin, timeout );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Utils::target_env_call( const QStringList& args,
|
||||||
|
const QString& stdin,
|
||||||
|
int timeout ) const
|
||||||
|
{
|
||||||
|
return CalamaresUtils::System::instance()->
|
||||||
|
targetEnvCall( args, QString(), stdin, timeout );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Utils::check_target_env_call( const QString& command,
|
||||||
|
const QString& stdin,
|
||||||
|
int timeout ) const
|
||||||
|
{
|
||||||
|
int ec = target_env_call( command, stdin, timeout );
|
||||||
|
return _handle_check_target_env_call_error( ec, command );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Utils::check_target_env_call( const QStringList& args,
|
||||||
|
const QString& stdin,
|
||||||
|
int timeout) const
|
||||||
|
{
|
||||||
|
int ec = target_env_call( args, stdin, timeout );
|
||||||
|
return _handle_check_target_env_call_error( ec, args.join( ' ' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString
|
||||||
|
Utils::check_target_env_output( const QString& command,
|
||||||
|
const QString& stdin,
|
||||||
|
int timeout ) const
|
||||||
|
{
|
||||||
|
QString output;
|
||||||
|
int ec = CalamaresUtils::System::instance()->
|
||||||
|
targetEnvOutput( command,
|
||||||
|
output,
|
||||||
|
QString(),
|
||||||
|
stdin,
|
||||||
|
timeout );
|
||||||
|
_handle_check_target_env_call_error( ec, command );
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString
|
||||||
|
Utils::check_target_env_output( const QStringList& args,
|
||||||
|
const QString& stdin,
|
||||||
|
int timeout ) const
|
||||||
|
{
|
||||||
|
QString output;
|
||||||
|
int ec = CalamaresUtils::System::instance()->
|
||||||
|
targetEnvOutput( args,
|
||||||
|
output,
|
||||||
|
QString(),
|
||||||
|
stdin,
|
||||||
|
timeout );
|
||||||
|
_handle_check_target_env_call_error( ec, args.join( ' ' ) );
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString
|
||||||
|
Utils::obscure( const QString& string ) const
|
||||||
|
{
|
||||||
|
return CalamaresUtils::obscure( string );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Utils::_handle_check_target_env_call_error( int ec, const QString& cmd) const
|
||||||
|
{
|
||||||
|
if ( ec )
|
||||||
|
{
|
||||||
|
QString raise = QString( "raise subprocess.CalledProcessError(%1,\"%2\")" )
|
||||||
|
.arg( ec )
|
||||||
|
.arg( cmd );
|
||||||
|
PythonQt::self()->evalScript( m_exceptionCxt, raise );
|
||||||
|
}
|
||||||
|
return ec;
|
||||||
|
}
|
74
src/libcalamaresui/viewpages/PythonQtUtilsWrapper.h
Normal file
74
src/libcalamaresui/viewpages/PythonQtUtilsWrapper.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Calamares 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PYTHONQTUTILSWRAPPER_H
|
||||||
|
#define PYTHONQTUTILSWRAPPER_H
|
||||||
|
|
||||||
|
#include <PythonQtObjectPtr.h>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
|
||||||
|
class Utils : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit Utils( QObject* parent = nullptr );
|
||||||
|
virtual ~Utils() {}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void debug( const QString& s ) const;
|
||||||
|
|
||||||
|
int mount( const QString& device_path,
|
||||||
|
const QString& mount_point,
|
||||||
|
const QString& filesystem_name,
|
||||||
|
const QString& options ) const;
|
||||||
|
|
||||||
|
int target_env_call( const QString& command,
|
||||||
|
const QString& stdin = QString(),
|
||||||
|
int timeout = 0 ) const;
|
||||||
|
|
||||||
|
int target_env_call( const QStringList& args,
|
||||||
|
const QString& stdin = QString(),
|
||||||
|
int timeout = 0 ) const;
|
||||||
|
|
||||||
|
int check_target_env_call( const QString& command,
|
||||||
|
const QString& stdin = QString(),
|
||||||
|
int timeout = 0 ) const;
|
||||||
|
|
||||||
|
int check_target_env_call( const QStringList& args,
|
||||||
|
const QString& stdin = QString(),
|
||||||
|
int timeout = 0 ) const;
|
||||||
|
|
||||||
|
QString check_target_env_output( const QString& command,
|
||||||
|
const QString& stdin = QString(),
|
||||||
|
int timeout = 0 ) const;
|
||||||
|
|
||||||
|
QString check_target_env_output( const QStringList& args,
|
||||||
|
const QString& stdin = QString(),
|
||||||
|
int timeout = 0 ) const;
|
||||||
|
|
||||||
|
QString obscure( const QString& string ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline int _handle_check_target_env_call_error( int ec, const QString& cmd ) const;
|
||||||
|
|
||||||
|
PythonQtObjectPtr m_exceptionCxt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PYTHONQTUTILSWRAPPER_H
|
206
src/libcalamaresui/viewpages/PythonQtViewStep.cpp
Normal file
206
src/libcalamaresui/viewpages/PythonQtViewStep.cpp
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Calamares 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PythonQtViewStep.h"
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
#include "utils/CalamaresUtilsGui.h"
|
||||||
|
#include "utils/PythonQtUtils.h"
|
||||||
|
#include "utils/Retranslator.h"
|
||||||
|
#include "viewpages/PythonQtJob.h"
|
||||||
|
|
||||||
|
#include <gui/PythonQtScriptingConsole.h>
|
||||||
|
|
||||||
|
#include <QBoxLayout>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Calamares
|
||||||
|
{
|
||||||
|
|
||||||
|
PythonQtViewStep::PythonQtViewStep( PythonQtObjectPtr cxt,
|
||||||
|
QObject* parent )
|
||||||
|
: ViewStep( parent )
|
||||||
|
, m_widget( new QWidget() )
|
||||||
|
, m_cxt( cxt )
|
||||||
|
{
|
||||||
|
PythonQt* pq = PythonQt::self();
|
||||||
|
Q_ASSERT( pq );
|
||||||
|
|
||||||
|
// The @calamares_module decorator should have filled _calamares_module_typename
|
||||||
|
// for us.
|
||||||
|
QString className = m_cxt.getVariable( "_calamares_module_typename" ).toString();
|
||||||
|
|
||||||
|
// Instantiate an object of the class marked with @calamares_module and
|
||||||
|
// store it as _calamares_module.
|
||||||
|
pq->evalScript( m_cxt, QString( "_calamares_module = %1()" )
|
||||||
|
.arg( className ) );
|
||||||
|
m_obj = pq->lookupObject( m_cxt, "_calamares_module" );
|
||||||
|
|
||||||
|
Q_ASSERT( !m_obj.isNull() ); // no entry point, no party
|
||||||
|
|
||||||
|
// Prepare the base widget for the module's pages
|
||||||
|
m_widget->setLayout( new QVBoxLayout );
|
||||||
|
CalamaresUtils::unmarginLayout( m_widget->layout() );
|
||||||
|
m_cxt.addObject( "_calamares_module_basewidget", m_widget );
|
||||||
|
|
||||||
|
CALAMARES_RETRANSLATE(
|
||||||
|
CalamaresUtils::lookupAndCall( m_obj, { "retranslate" } );
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString
|
||||||
|
PythonQtViewStep::prettyName() const
|
||||||
|
{
|
||||||
|
return CalamaresUtils::lookupAndCall( m_obj,
|
||||||
|
{ "prettyName",
|
||||||
|
"prettyname",
|
||||||
|
"pretty_name" } ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QWidget*
|
||||||
|
PythonQtViewStep::widget()
|
||||||
|
{
|
||||||
|
if ( m_widget->layout()->count() > 1 )
|
||||||
|
cDebug() << "WARNING: PythonQtViewStep wrapper widget has more than 1 child. "
|
||||||
|
"This should never happen.";
|
||||||
|
|
||||||
|
bool nothingChanged = m_cxt.evalScript(
|
||||||
|
"_calamares_module.widget() in _calamares_module_basewidget.children()" ).toBool();
|
||||||
|
if ( nothingChanged )
|
||||||
|
return m_widget;
|
||||||
|
|
||||||
|
// Else, we either don't have a child widget, or we have a child widget that
|
||||||
|
// was previously set and doesn't apply any more since the Python module
|
||||||
|
// set a new one.
|
||||||
|
|
||||||
|
// First we clear the layout, which should only ever have 1 item.
|
||||||
|
// We only remove from the layout and not delete because Python is in charge
|
||||||
|
// of memory management for these widgets.
|
||||||
|
while ( m_widget->layout()->itemAt( 0 ) )
|
||||||
|
m_widget->layout()->takeAt( 0 );
|
||||||
|
|
||||||
|
m_cxt.evalScript(
|
||||||
|
"_calamares_module_basewidget.layout().addWidget(_calamares_module.widget())" );
|
||||||
|
|
||||||
|
return m_widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PythonQtViewStep::next()
|
||||||
|
{
|
||||||
|
CalamaresUtils::lookupAndCall( m_obj, { "next" } );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PythonQtViewStep::back()
|
||||||
|
{
|
||||||
|
CalamaresUtils::lookupAndCall( m_obj, { "back" } );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PythonQtViewStep::isNextEnabled() const
|
||||||
|
{
|
||||||
|
return CalamaresUtils::lookupAndCall( m_obj,
|
||||||
|
{ "isNextEnabled",
|
||||||
|
"isnextenabled",
|
||||||
|
"is_next_enabled" } ).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PythonQtViewStep::isBackEnabled() const
|
||||||
|
{
|
||||||
|
return CalamaresUtils::lookupAndCall( m_obj,
|
||||||
|
{ "isBackEnabled",
|
||||||
|
"isbackenabled",
|
||||||
|
"is_back_enabled" } ).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PythonQtViewStep::isAtBeginning() const
|
||||||
|
{
|
||||||
|
return CalamaresUtils::lookupAndCall( m_obj,
|
||||||
|
{ "isAtBeginning",
|
||||||
|
"isatbeginning",
|
||||||
|
"is_at_beginning" } ).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PythonQtViewStep::isAtEnd() const
|
||||||
|
{
|
||||||
|
return CalamaresUtils::lookupAndCall( m_obj,
|
||||||
|
{ "isAtEnd",
|
||||||
|
"isatend",
|
||||||
|
"is_at_end" } ).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QList< Calamares::job_ptr >
|
||||||
|
PythonQtViewStep::jobs() const
|
||||||
|
{
|
||||||
|
QList< Calamares::job_ptr > jobs;
|
||||||
|
|
||||||
|
PythonQtObjectPtr jobsCallable = PythonQt::self()->lookupCallable( m_obj, "jobs" );
|
||||||
|
if ( jobsCallable.isNull() )
|
||||||
|
return jobs;
|
||||||
|
|
||||||
|
PythonQtObjectPtr response = PythonQt::self()->callAndReturnPyObject( jobsCallable );
|
||||||
|
if ( response.isNull() )
|
||||||
|
return jobs;
|
||||||
|
|
||||||
|
PythonQtObjectPtr listPopCallable = PythonQt::self()->lookupCallable( response, "pop" );
|
||||||
|
if ( listPopCallable.isNull() )
|
||||||
|
return jobs;
|
||||||
|
|
||||||
|
forever
|
||||||
|
{
|
||||||
|
PythonQtObjectPtr aJob = PythonQt::self()->callAndReturnPyObject( listPopCallable, { 0 } );
|
||||||
|
if ( aJob.isNull() )
|
||||||
|
break;
|
||||||
|
|
||||||
|
jobs.append( Calamares::job_ptr( new PythonQtJob( m_cxt, aJob ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return jobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PythonQtViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||||
|
{
|
||||||
|
m_obj.addVariable( "configuration", configurationMap );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QWidget*
|
||||||
|
PythonQtViewStep::createScriptingConsole()
|
||||||
|
{
|
||||||
|
PythonQtScriptingConsole* console = new PythonQtScriptingConsole( nullptr, m_cxt );
|
||||||
|
console->setProperty( "classname",
|
||||||
|
m_cxt.getVariable( "_calamares_module_typename" ).toString() );
|
||||||
|
return console;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
65
src/libcalamaresui/viewpages/PythonQtViewStep.h
Normal file
65
src/libcalamaresui/viewpages/PythonQtViewStep.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Calamares 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PYTHONQTVIEWSTEP_H
|
||||||
|
#define PYTHONQTVIEWSTEP_H
|
||||||
|
|
||||||
|
#include "ViewStep.h"
|
||||||
|
|
||||||
|
#include <PythonQt.h>
|
||||||
|
|
||||||
|
namespace Calamares
|
||||||
|
{
|
||||||
|
|
||||||
|
class PythonQtViewStep : public Calamares::ViewStep
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
PythonQtViewStep( PythonQtObjectPtr cxt,
|
||||||
|
QObject* parent = nullptr );
|
||||||
|
|
||||||
|
QString prettyName() const override;
|
||||||
|
|
||||||
|
QWidget* widget() override;
|
||||||
|
|
||||||
|
void next() override;
|
||||||
|
void back() override;
|
||||||
|
|
||||||
|
bool isNextEnabled() const override;
|
||||||
|
bool isBackEnabled() const override;
|
||||||
|
|
||||||
|
bool isAtBeginning() const override;
|
||||||
|
bool isAtEnd() const override;
|
||||||
|
|
||||||
|
QList< Calamares::job_ptr > jobs() const override;
|
||||||
|
|
||||||
|
void setConfigurationMap( const QVariantMap& configurationMap ) override;
|
||||||
|
|
||||||
|
QWidget* createScriptingConsole();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QWidget* m_widget;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PythonQtObjectPtr m_cxt;
|
||||||
|
PythonQtObjectPtr m_obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PYTHONQTVIEWSTEP_H
|
18
src/modules/dummypythonqt/dummypythonqt.conf
Normal file
18
src/modules/dummypythonqt/dummypythonqt.conf
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
syntax: "YAML map of anything"
|
||||||
|
example:
|
||||||
|
whats_this: "module-specific configuration"
|
||||||
|
from_where: "dummypythonqt.conf"
|
||||||
|
a_list:
|
||||||
|
- "item1"
|
||||||
|
- "item2"
|
||||||
|
- "item3"
|
||||||
|
- "item4"
|
||||||
|
a_list_of_maps:
|
||||||
|
- name: "an Item"
|
||||||
|
contents:
|
||||||
|
- "an element"
|
||||||
|
- "another element"
|
||||||
|
- name: "another item"
|
||||||
|
contents:
|
||||||
|
- "not much"
|
115
src/modules/dummypythonqt/main.py
Normal file
115
src/modules/dummypythonqt/main.py
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
#
|
||||||
|
# Copyright 2016, Teo Mrnjavac <teo@kde.org>
|
||||||
|
#
|
||||||
|
# Calamares 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 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import platform
|
||||||
|
|
||||||
|
from PythonQt.QtGui import *
|
||||||
|
import PythonQt.calamares as calamares
|
||||||
|
|
||||||
|
# Set up translations.
|
||||||
|
# You may skip this if your Calamares module has no user visible strings.
|
||||||
|
# DO NOT install _ into the builtin namespace because each module loads
|
||||||
|
# its own catalog.
|
||||||
|
# DO use the gettext class-based API and manually alias _ as described in:
|
||||||
|
# https://docs.python.org/3.5/library/gettext.html#localizing-your-module
|
||||||
|
import gettext
|
||||||
|
import inspect
|
||||||
|
import os
|
||||||
|
filename = inspect.getframeinfo(inspect.currentframe()).filename
|
||||||
|
path = os.path.dirname(os.path.abspath(filename))
|
||||||
|
# t = gettext.translation('dummypythonqt',
|
||||||
|
# os.path.join(path, 'lang'),
|
||||||
|
# languages=['en'])
|
||||||
|
#_ = t.lgettext
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
# Example Python ViewModule.
|
||||||
|
# A Python ViewModule is a Python program which defines a ViewStep class.
|
||||||
|
# This class must be marked with the @calamares_module decorator. A
|
||||||
|
# ViewModule may define other classes, but only one may be decorated with
|
||||||
|
# @calamares_module. Such a class must conform to the Calamares ViewStep
|
||||||
|
# interface and functions as the entry point of the module.
|
||||||
|
# A ViewStep manages one or more "wizard pages" through methods like
|
||||||
|
# back/next, and reports its status through isNextEnabled/isBackEnabled/
|
||||||
|
# isAtBeginning/isAtEnd. The whole UI, including all the pages, must be
|
||||||
|
# exposed as a single QWidget, returned by the widget function.
|
||||||
|
@calamares_module
|
||||||
|
class DummyPythonQtViewStep():
|
||||||
|
def __init__(self):
|
||||||
|
self.main_widget = QFrame()
|
||||||
|
|
||||||
|
self.main_widget.setLayout(QVBoxLayout())
|
||||||
|
|
||||||
|
label = QLabel()
|
||||||
|
self.main_widget.layout().addWidget(label)
|
||||||
|
|
||||||
|
accumulator = "\nCalamares+PythonQt running embedded Python " +\
|
||||||
|
platform.python_version()
|
||||||
|
label.text = accumulator
|
||||||
|
|
||||||
|
btn = QPushButton()
|
||||||
|
btn.setText(_("Click me!"))
|
||||||
|
self.main_widget.layout().addWidget(btn)
|
||||||
|
btn.connect("clicked(bool)", self.on_btn_clicked)
|
||||||
|
|
||||||
|
def on_btn_clicked(self):
|
||||||
|
self.main_widget.layout().addWidget(QLabel("A new QLabel."))
|
||||||
|
|
||||||
|
def prettyName(self):
|
||||||
|
return "Dummy PythonQt ViewStep"
|
||||||
|
|
||||||
|
def isNextEnabled(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def isBackEnabled(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def isAtBeginning(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def isAtEnd(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def jobs(self):
|
||||||
|
return [DummyPQJob("hi there lol")]
|
||||||
|
|
||||||
|
def widget(self):
|
||||||
|
return self.main_widget
|
||||||
|
|
||||||
|
|
||||||
|
class DummyPQJob():
|
||||||
|
def __init__(self, my_msg):
|
||||||
|
self.my_msg = my_msg
|
||||||
|
|
||||||
|
def pretty_name(self):
|
||||||
|
return _("The Dummy PythonQt Job")
|
||||||
|
|
||||||
|
def pretty_description(self):
|
||||||
|
return _("This description says that the Dummy PythonQt Job is a dummy. "
|
||||||
|
"The dummy job says: {}".format(self.my_msg))
|
||||||
|
|
||||||
|
def pretty_status_message(self):
|
||||||
|
return _("A status message for DPQ Job.")
|
||||||
|
|
||||||
|
def exec(self):
|
||||||
|
rmp = calamares.global_storage['rootMountPoint']
|
||||||
|
os.system("touch {}/calamares_dpqt_was_here".format(rmp))
|
||||||
|
calamares.utils.debug("the dummy job says {}".format(self.my_msg))
|
||||||
|
return {'ok': True}
|
7
src/modules/dummypythonqt/module.desc
Normal file
7
src/modules/dummypythonqt/module.desc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Module metadata file for dummy pythonqt jobmodule
|
||||||
|
# Syntax is YAML 1.2
|
||||||
|
---
|
||||||
|
type: "view"
|
||||||
|
name: "dummypythonqt"
|
||||||
|
interface: "pythonqt"
|
||||||
|
script: "main.py" #assumed relative to the current directory
|
Loading…
Reference in New Issue
Block a user