diff --git a/tools/plugingenerator/config.json b/tools/plugingenerator/config.json index 3ba3c4c9ca..78f36c2d89 100644 --- a/tools/plugingenerator/config.json +++ b/tools/plugingenerator/config.json @@ -1,4 +1,9 @@ { + "pdk":{ + "enable": true, + "deps_path": "", + "project_path": "" + }, "plugin": { "dir_name": "new", "plugin_name": "newplugin", diff --git a/tools/plugingenerator/plugin_generator.py b/tools/plugingenerator/plugin_generator.py index 7e176c0d54..b1452e809c 100644 --- a/tools/plugingenerator/plugin_generator.py +++ b/tools/plugingenerator/plugin_generator.py @@ -25,11 +25,6 @@ pathToScopy = args.scopy_path else: pathToScopy = os.path.dirname(os.path.dirname(os.getcwd())) - -pluginsPath = os.path.join(pathToScopy, "plugins") -if not os.path.exists(pluginsPath): - print("Couldn't find " + pluginsPath + " path!") - exit(1) pathToConfigFile = "" if args.config_file_path: @@ -49,6 +44,7 @@ filesGenerated = [] directoriesGenerated = [] +pdkSupport = generatorOptions["pdk"]["enable"] pluginDirName = generatorOptions["plugin"]["dir_name"] pluginName = generatorOptions["plugin"]["plugin_name"] pluginDisplayName = generatorOptions["plugin"]["plugin_display_name"] @@ -57,6 +53,32 @@ pluginExportMacro = "SCOPY_" + pluginName.upper() + "_EXPORT" print("Starting file generation:") + +pluginsPath = os.path.join(pathToScopy, "plugins") +if pdkSupport: + pdkPath = generatorOptions["pdk"]["project_path"] + if not pdkPath: + pdkPath = os.path.join(pathToScopy, "ScopyPluginRunner") + else: + pdkPath = os.path.join(pdkPath, "ScopyPluginRunner") + try: + os.makedirs(pdkPath, mode) + directoriesGenerated.append(pdkPath) + except FileExistsError: + print(pdkPath + " directory already exists!") + + pluginsPath = os.path.join(pdkPath, "plugin") + try: + os.mkdir(pluginsPath, mode) + directoriesGenerated.append(pluginsPath) + except FileExistsError: + print(pluginsPath + " directory already exists!") + + +if not os.path.exists(pluginsPath): + print("Couldn't find " + pluginsPath + " path!") + exit(1) + #################################################### Plugin dir ############################################# newPluginPath = os.path.join(pluginsPath, pluginDirName) if not os.path.exists(newPluginPath): @@ -98,6 +120,127 @@ else: print(pluginSrcConfigPath + " file already exists!") +####################################################### pdk ################################################## +if pdkSupport: + scopyPdkDeps = generatorOptions["pdk"]["deps_path"] + pdkPreferencesPath = os.path.join(pdkPath, "preferences.ini") + if not os.path.exists(pdkPreferencesPath): + pdkPreferences = open(pdkPreferencesPath, "w") + pdkPreferences.close() + + pdkCmakeFuncFilePath = os.path.join(pdkPath, "PdkSupport.cmake") + if not os.path.exists(pdkCmakeFuncFilePath): + pdkCmakeFuncTemplate = Template( + filename="templates/pdk/pdk_cmake_func_template.mako" + ) + pdkCmakeFuncContent = pdkCmakeFuncTemplate.render() + pdkCmakeFuncFile = open(pdkCmakeFuncFilePath, "w") + pdkCmakeFuncFile.write(pdkCmakeFuncContent) + pdkCmakeFuncFile.close() + filesGenerated.append(pdkCmakeFuncFilePath) + else: + print(pdkCmakeFuncFilePath + " file already exists!") + + pdkCmakeFilePath = os.path.join(pdkPath, "CMakeLists.txt") + if not os.path.exists(pdkCmakeFilePath): + pdkCmakeTemplate = Template( + filename="templates/pdk/pdk_cmake_template.mako" + ) + pdkCmakeContent = pdkCmakeTemplate.render( + deps_path=scopyPdkDeps, + plugin_dir=pluginDirName, + plugin_name=pluginName, + preferences_path = pdkPreferencesPath + ) + pdkCmakeFile = open(pdkCmakeFilePath, "w") + pdkCmakeFile.write(pdkCmakeContent) + pdkCmakeFile.close() + filesGenerated.append(pdkCmakeFilePath) + else: + print(pdkCmakeFilePath + " file already exists!") + + pdkIncludePath = os.path.join(pdkPath, "include") + try: + os.mkdir(pdkIncludePath, mode) + directoriesGenerated.append(pdkIncludePath) + except FileExistsError: + print(pdkIncludePath + " directory already exists!") + + pdkHeaderFilePath = os.path.join(pdkIncludePath, "pdkwindow.h") + if not os.path.exists(pdkHeaderFilePath): + pdkHeaderTemplate = Template( + filename="templates/pdk/pdk_header_template.mako" + ) + pdkHeaderContent = pdkHeaderTemplate.render() + pdkHeaderFile = open(pdkHeaderFilePath, "w") + pdkHeaderFile.write(pdkHeaderContent) + pdkHeaderFile.close() + filesGenerated.append(pdkHeaderFilePath) + else: + print(pdkHeaderFilePath + " file already exists!") + + pdkCmakeInFilePath = os.path.join(pdkIncludePath, "pdk-util_config.h.cmakein") + if not os.path.exists(pdkCmakeInFilePath): + pdkCmakeInTemplate = Template( + filename="templates/pdk/pdk_cmakein_template.mako" + ) + pdkCmakeInTemplate = pdkCmakeInTemplate.render() + pdkCmakeInFile = open(pdkCmakeInFilePath, "w") + pdkCmakeInFile.write(pdkCmakeInTemplate) + pdkCmakeInFile.close() + filesGenerated.append(pdkCmakeInFilePath) + else: + print(pdkCmakeInFilePath + " file already exists!") + + pdkSrcPath = os.path.join(pdkPath, "src") + try: + os.mkdir(pdkSrcPath, mode) + directoriesGenerated.append(pdkSrcPath) + except FileExistsError: + print(pdkSrcPath + " directory already exists!") + + pdkSrcFilePath = os.path.join(pdkSrcPath, "main.cpp") + if not os.path.exists(pdkSrcFilePath): + pdkSrcTemplate = Template( + filename="templates/pdk/pdk_src_template.mako" + ) + pdkSrcContent = pdkSrcTemplate.render() + pdkSrcFile = open(pdkSrcFilePath, "w") + pdkSrcFile.write(pdkSrcContent) + pdkSrcFile.close() + filesGenerated.append(pdkSrcFilePath) + + pdkResPath = os.path.join(pdkPath, "res") + try: + os.mkdir(pdkResPath, mode) + directoriesGenerated.append(pdkResPath) + except FileExistsError: + print(pdkResPath + " directory already exists!") + + qssPdkPath = os.path.join(pdkResPath,"default.qss") + defaultQssPath = os.path.join(scopyPdkDeps,"usr/local/resources/stylesheets/default.qss") + if not os.path.exists(defaultQssPath): + defaultQssPath = os.path.join(pathToScopy,"gui/res/stylesheets/default.qss") + + if os.path.exists(defaultQssPath): + if not os.path.exists(qssPdkPath): + shutil.copy(defaultQssPath,pdkResPath) + else: + print(qssPdkPath + " file already exists!") + else: + print("default.qss stylesheet couldn't be found!") + pdkResQrc = os.path.join(pdkResPath, "resources.qrc") + if not os.path.exists(pdkResQrc): + resFile = open(pdkResQrc, "w") + resFile.write("\n") + resFile.write(" \n") + if os.path.exists(qssPdkPath): + resFile.write(" default.qss\n") + resFile.write(" \n") + resFile.write("") + resFile.close() + filesGenerated.append(pdkResQrc) + ##################################################### Include ################################################ includePath = os.path.join(newPluginPath, "include") try: @@ -171,8 +314,9 @@ + str(generatorOptions["test"]["cmake_min_required"]) + ")\n\n" ) - if generatorOptions["test"]["tst_pluginloader"]: - testCmakeFile.write("include(ScopyTest)\n\nsetup_scopy_tests(pluginloader)") + if not pdkSupport: + if generatorOptions["test"]["tst_pluginloader"]: + testCmakeFile.write("include(ScopyTest)\n\nsetup_scopy_tests(pluginloader)") filesGenerated.append(testCmakePath) else: print(testCmakePath + " file already exists!") @@ -214,13 +358,16 @@ print(resQrc + " file already exists!") ##################################################### Plugin CMakeLists ######################################### + if generatorOptions["plugin"]["cmakelists"]: cmakeListsPath = os.path.join(newPluginPath, "CMakeLists.txt") cmakeTemplate = Template(filename="templates/cmakelists_template.mako") + cmakeContent = cmakeTemplate.render( - scopy_module=pluginName, - plugin_display_name=pluginDisplayName, - plugin_description=pluginDecription, config=generatorOptions["cmakelists"] + pdk_en=pdkSupport, + scopy_module=pluginName, + plugin_display_name=pluginDisplayName, + plugin_description=pluginDecription, config=generatorOptions["cmakelists"] ) if not os.path.exists(cmakeListsPath): @@ -247,7 +394,7 @@ filesGenerated.append(cmakeinFilePath) else: - print(cmakeinFilePath + " file already exists!") + print(cmakeinFilePath + " file already exists!") ##################################################### Plugin ToolList ######################################### diff --git a/tools/plugingenerator/templates/cmakelists_template.mako b/tools/plugingenerator/templates/cmakelists_template.mako index dede1117ef..306fbe03a1 100644 --- a/tools/plugingenerator/templates/cmakelists_template.mako +++ b/tools/plugingenerator/templates/cmakelists_template.mako @@ -65,6 +65,17 @@ configure_file( target_include_directories(${"${PROJECT_NAME}"} INTERFACE ${"${CMAKE_CURRENT_SOURCE_DIR}"}/include) target_include_directories(${"${PROJECT_NAME}"} PRIVATE ${"${CMAKE_CURRENT_SOURCE_DIR}"}/include/${"${SCOPY_MODULE}"}) +% if pdk_en: +target_include_directories(${"${PROJECT_NAME}"} PRIVATE ${"${PDK_DEPS_INCLUDE}"}) + +include(${"${CMAKE_SOURCE_DIR}"}/PdkSupport.cmake) +inlcude_dirs(${"${PDK_DEPS_INCLUDE}"}) + +target_link_libraries(${"${PROJECT_NAME}"} PUBLIC Qt::Widgets Qt::Core) + +link_libs(${"${PDK_DEPS_LIB}"}) + +% else: target_include_directories(${"${PROJECT_NAME}"} PUBLIC scopy-pluginbase scopy-gui) target_link_libraries( @@ -76,6 +87,8 @@ target_link_libraries( scopy-iioutil ) +% endif + if(${"${CMAKE_SYSTEM_NAME}"} MATCHES "Windows") configureinstallersettings(${"${SCOPY_MODULE}"} ${"${PLUGIN_DESCRIPTION}"} FALSE) endif() diff --git a/tools/plugingenerator/templates/pdk/pdk_cmake_func_template.mako b/tools/plugingenerator/templates/pdk/pdk_cmake_func_template.mako new file mode 100644 index 0000000000..1ffb4998c5 --- /dev/null +++ b/tools/plugingenerator/templates/pdk/pdk_cmake_func_template.mako @@ -0,0 +1,25 @@ +# Define a function to include all directories recursively +function(inlcude_dirs root_dir) + # Find all files and directories recursively + file(GLOB_RECURSE all_items LIST_DIRECTORIES true ""${"${root_dir}"}/"") + # Loop through each item found + foreach(item ${"${all_items}"}) + # Check if the item is a directory + if(IS_DIRECTORY ${"${item}"}) + message(${"${item}"}) + target_include_directories(${"${PROJECT_NAME}"} PRIVATE ${"${item}"}) + endif() + endforeach() +endfunction() + +# Define a function to link all .so files from a root directory +function(link_libs root_dir) + # Find all .so files from root_dir + file(GLOB all_libs "${"${root_dir}"}/*.so") + # Loop through each library found + foreach(lib ${"${all_libs}"}) + # Link libraries + message(${"${lib}"}) + target_link_libraries(${"${PROJECT_NAME}"} PRIVATE ${"${lib}"}) + endforeach() +endfunction() \ No newline at end of file diff --git a/tools/plugingenerator/templates/pdk/pdk_cmake_template.mako b/tools/plugingenerator/templates/pdk/pdk_cmake_template.mako new file mode 100644 index 0000000000..d5feba4bd5 --- /dev/null +++ b/tools/plugingenerator/templates/pdk/pdk_cmake_template.mako @@ -0,0 +1,66 @@ +cmake_minimum_required(VERSION 3.9) + +# Project name +set(TARGET_NAME "ScopyPluginRunner") + +project(${"${TARGET_NAME}"} VERSION 0.0.1 DESCRIPTION "Project Description") + +# Make sure CMake will take care of moc for us +set(CMAKE_AUTOMOC ON) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(PDK_DEPS_PATH ${deps_path}) +if(NOT DEFINED PDK_DEPS_PATH) + message(FATAL_ERROR "PDK_DEPS_PATH is required!") +else() + if(NOT EXISTS ${"${PDK_DEPS_PATH}"}) + message(FATAL_ERROR "The path=" \"${"${PDK_DEPS_PATH}"}\" " to the dependencies doesn't exist!") + endif() +endif() +set(PDK_DEPS_INCLUDE ${"${PDK_DEPS_PATH}"}/usr/local/include) +if(NOT EXISTS ${"${PDK_DEPS_INCLUDE}"}) + message(FATAL_ERROR "The path=" \"${"${PDK_DEPS_INCLUDE}"}\" " to the headers doesn't exist!") +endif() + +set(PDK_DEPS_LIB ${"${PDK_DEPS_PATH}"}/usr/local/lib) +if(NOT EXISTS ${"${PDK_DEPS_LIB}"}) + message(FATAL_ERROR "The path=" \"${"${PDK_DEPS_LIB}"}\" " to the libraries doesn't exist!") +endif() + +set(PLUGIN_INSTALL_PATH ${"${CMAKE_CURRENT_BINARY_DIR}"}/plugin/${plugin_dir}/libscopy-${plugin_name}.so) +set(PATH_TO_INI ${preferences_path}) + +find_package(QT NAMES Qt5 REQUIRED COMPONENTS Widgets) +find_package(Qt${"${QT_VERSION_MAJOR}"} REQUIRED COMPONENTS Widgets Core) + +file(GLOB SRC_LIST src/*.cpp) +file(GLOB HEADER_LIST include/*.h include/*.hpp) + +configure_file(include/pdk-util_config.h.cmakein ${"${CMAKE_CURRENT_SOURCE_DIR}"}/include/pdk-util_config.h @ONLY) + +set(PROJECT_SOURCES ${"${SRC_LIST}"} ${"${HEADER_LIST}"} ${"${CMAKE_CURRENT_SOURCE_DIR}"}/include/pdk-util_config.h) +find_path(IIO_INCLUDE_DIRS iio.h REQUIRED) +find_library(IIO_LIBRARIES NAMES iio libiio REQUIRED) + +add_subdirectory(plugin/${plugin_dir}) + +qt_add_resources(PROJ_RES res/resources.qrc) + +add_executable(${"${TARGET_NAME}"} ${"${PROJECT_SOURCES}"} ${"${PROJ_RES}"}) + +include(${"${CMAKE_CURRENT_SOURCE_DIR}"}/PdkSupport.cmake) + +target_include_directories(${"${TARGET_NAME}"} PRIVATE ${"${Qt${QT_VERSION_MAJOR}_INCLUDE_DIRS}"}) +target_include_directories(${"${TARGET_NAME}"} PRIVATE ${"${CMAKE_SOURCE_DIR}"}/include) +target_include_directories(${"${TARGET_NAME}"} INTERFACE ${"${IIO_INCLUDE_DIRS}"}) + +target_include_directories(${"${TARGET_NAME}"} PUBLIC ${"${PDK_DEPS_INCLUDE}"} ${"${IIO_INCLUDE_DIRS}"}) + +inlcude_dirs(${"${PDK_DEPS_INCLUDE}"}) +# Add any extra libs to link also. +link_libs(${"${PDK_DEPS_LIB}"}) +target_link_libraries( + ${"${TARGET_NAME}"} PRIVATE Qt${"${QT_VERSION_MAJOR}"}::Widgets Qt${"${QT_VERSION_MAJOR}"}::Core ${"${IIO_LIBRARIES}"} +) diff --git a/tools/plugingenerator/templates/pdk/pdk_cmakein_template.mako b/tools/plugingenerator/templates/pdk/pdk_cmakein_template.mako new file mode 100644 index 0000000000..dd26174d7c --- /dev/null +++ b/tools/plugingenerator/templates/pdk/pdk_cmakein_template.mako @@ -0,0 +1,7 @@ +#ifndef PDK_UTIL_H_CMAKEIN +#define PDK_UTIL_H_CMAKEIN + +#define PLUGIN_INSTALL_PATH "@PLUGIN_INSTALL_PATH@" +#define PATH_TO_INI "@PATH_TO_INI@" + +#endif // PDK_UTIL_H_CMAKEIN diff --git a/tools/plugingenerator/templates/pdk/pdk_header_template.mako b/tools/plugingenerator/templates/pdk/pdk_header_template.mako new file mode 100644 index 0000000000..d033dd16ee --- /dev/null +++ b/tools/plugingenerator/templates/pdk/pdk_header_template.mako @@ -0,0 +1,146 @@ +#include "plugin.h" +#include "toolmenuentry.h" +#include +#include +#include +#include +#include +#include + +class MainWidget; +class PluginManager; + +class PDKWindow : public QMainWindow +{ + Q_OBJECT +public: + PDKWindow(QWidget *parent = nullptr); + ~PDKWindow(); + +public Q_SLOTS: + void onConnect(); + void onDisconnect(); + void onInit(); + void onDeinit(); + void onLoad(); + void onUnload(); +Q_SIGNALS: + void sigLabelTextUpdated(std::string_view); + +private: + QTabWidget *m_tabWidget; + QWidget *m_prefPage; + QList m_toolList; + QList m_loadedTools; + QLabel *m_aboutPage = nullptr; + MainWidget *m_mainWidget = nullptr; + + void initMainWindow(); + void updateLabelText(); + void initPreferencesPage(); + void addPluginPrefPage(); + void removePluginPrefPage(); + QLabel *createTabLabel(QString name); + QWidget *addHorizontalTab(QWidget *w, QLabel *lbl, bool tabEnabled = true); + QWidget *buildSaveSessionPreference(); + QWidget *generalPreferences(); + void initGeneralPreferences(); +}; + +class MainWidget : public QWidget +{ + Q_OBJECT +public: + MainWidget(QWidget *parent); + ~MainWidget(); + + QString pluginAbout(); + QWidget *pluginPrefPage(); + QList getPluginTools(); + +Q_SIGNALS: + void connected(); + void disconnected(); + void init(); + void deinit(); + void loaded(); + void unloaded(); + +private Q_SLOTS: + void onConnect(); + void onDisconnect(); + void deinitialize(); + void onInit(); + void onLoad(); + void onUnload(); + void browseFile(QLineEdit *pluginPathEdit); + void deletePluginManager(); + +private: + void unloadInfoPage(); + void loadInfoPage(); + void changeVisibility(QPushButton *btn1, QPushButton *btn2); + void enableBrowseInit(bool en); + void enableLoadConn(bool en); + void updateStatusLbl(QString msg); + void loadAvailCat(); + bool validConnection(QString uri, QString cat); + bool isCompatible(QString uri, QString cat); + + PluginManager *m_pluginManager; + QLabel *m_statusLbl; + QLineEdit *m_uriEdit; + QLineEdit *m_pluginPathEdit; + QPushButton *m_browseBtn; + QPushButton *m_initBtn; + QPushButton *m_loadBtn; + QPushButton *m_unloadBtn; + QPushButton *m_connBtn; + QPushButton *m_disconnBtn; + + QWidget *m_pluginIcon; + scopy::MenuCombo *m_deviceTypeCb; + QScrollArea *m_scrollArea; + QString m_currentPlugin; + enum State + { + Unloaded, + Loaded, + Connected + } m_state; +}; + +class PluginManager : public QObject +{ + Q_OBJECT +public: + PluginManager(QString pluginPath, QObject *parent = nullptr); + ~PluginManager(); + + scopy::Plugin *plugin() const; + bool pluginCompatibility(QString param, QString category); + +Q_SIGNALS: + void requestTool(QString toolId); + +private: + void initPlugin(); + void loadPlugin(QString file); + + scopy::Plugin *m_plugin; + bool m_loaded; +}; + +class ConnectionStrategy : public QObject +{ + Q_OBJECT +public: + ConnectionStrategy(QString uri, QObject *parent = nullptr); + ~ConnectionStrategy(); + bool validConnection(QString cat); + +private: + bool iioConn(); + bool testConn(); + QString m_uri; +}; diff --git a/tools/plugingenerator/templates/pdk/pdk_src_template.mako b/tools/plugingenerator/templates/pdk/pdk_src_template.mako new file mode 100644 index 0000000000..b5a570bf70 --- /dev/null +++ b/tools/plugingenerator/templates/pdk/pdk_src_template.mako @@ -0,0 +1,820 @@ +#include "pdkwindow.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gui/stylehelper.h" +#include "gui/preferenceshelper.h" +#include "pdk-util_config.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QCoreApplication::setOrganizationName("ADI"); + QCoreApplication::setOrganizationDomain("analog.com"); + QCoreApplication::setApplicationName("Scopy-PDK"); + QSettings::setDefaultFormat(QSettings::IniFormat); + + QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + app.setStyleSheet(Util::loadStylesheetFromFile(":/default.qss")); + PDKWindow test; + test.show(); + int ret = app.exec(); + if(ret == 0) { + qInfo() << "PDK support finished successfully!"; + } + return ret; +} + +PDKWindow::PDKWindow(QWidget *parent) + : QMainWindow(parent) +{ + setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + setMinimumSize(1280, 720); + layout()->setMargin(9); + layout()->setSpacing(6); + scopy::StyleHelper::GetInstance()->initColorMap(); + m_mainWidget = new MainWidget(this); + m_aboutPage = new QLabel(this); + m_aboutPage->setWordWrap(true); + m_aboutPage->setAlignment(Qt::AlignTop); + initMainWindow(); + initPreferencesPage(); + + addHorizontalTab(m_mainWidget, createTabLabel("Main")); + addHorizontalTab(m_aboutPage, createTabLabel("About")); + addHorizontalTab(m_prefPage, createTabLabel("Preferences")); + connect(m_mainWidget, &MainWidget::connected, this, &PDKWindow::onConnect); + connect(m_mainWidget, &MainWidget::disconnected, this, &PDKWindow::onDisconnect); + connect(m_mainWidget, &MainWidget::init, this, &PDKWindow::onInit); + connect(m_mainWidget, &MainWidget::deinit, this, &PDKWindow::onDeinit); + connect(m_mainWidget, &MainWidget::loaded, this, &PDKWindow::onLoad); + connect(m_mainWidget, &MainWidget::unloaded, this, &PDKWindow::onUnload); +} + +PDKWindow::~PDKWindow() +{ + if(m_mainWidget) { + delete m_mainWidget; + m_mainWidget = nullptr; + } +} + +void PDKWindow::onConnect() +{ + if(!m_loadedTools.isEmpty()) { + onUnload(); + } + QList tools = m_mainWidget->getPluginTools(); + for(const scopy::ToolMenuEntry *t : qAsConst(tools)) { + if(!t->tool()) + continue; + QLabel *lbl = createTabLabel(t->name()); + QWidget *tab = addHorizontalTab(t->tool(), lbl); + connect(t, &scopy::ToolMenuEntry::updateToolEntry, this, [lbl, t]() { + if(lbl->text().compare(t->name()) != 0) { + lbl->setText(t->name()); + } + }); + m_toolList.append(tab); + } +} + +void PDKWindow::onDisconnect() +{ + QList tools = m_mainWidget->getPluginTools(); + for(const scopy::ToolMenuEntry *t : qAsConst(tools)) { + t->disconnect(this); + } + for(auto t : qAsConst(m_toolList)) { + int idx = m_tabWidget->indexOf(t); + m_tabWidget->removeTab(idx); + m_toolList.removeOne(t); + } + onLoad(); +} + +void PDKWindow::onInit() +{ + addPluginPrefPage(); + m_aboutPage->clear(); + m_aboutPage->setText(m_mainWidget->pluginAbout()); +} + +void PDKWindow::onDeinit() +{ + m_aboutPage->clear(); + removePluginPrefPage(); +} + +void PDKWindow::onLoad() +{ + QList tools = m_mainWidget->getPluginTools(); + for(const scopy::ToolMenuEntry *t : qAsConst(tools)) { + if(t->name().isEmpty()) + continue; + QLabel *lbl = createTabLabel(t->name()); + QWidget *tab = addHorizontalTab(new QWidget(), lbl, false); + m_loadedTools.append(tab); + } +} + +void PDKWindow::onUnload() +{ + if(m_loadedTools.isEmpty()) + return; + for(auto t : qAsConst(m_loadedTools)) { + int idx = m_tabWidget->indexOf(t); + m_tabWidget->removeTab(idx); + m_loadedTools.removeOne(t); + } +} + +QWidget *PDKWindow::buildSaveSessionPreference() +{ + scopy::Preferences *p = scopy::Preferences::GetInstance(); + QWidget *w = new QWidget(this); + QHBoxLayout *lay = new QHBoxLayout(w); + lay->setMargin(0); + + lay->addWidget(scopy::PreferencesHelper::addPreferenceCheckBox(p, "general_save_session", + "Save/Load Scopy session", this)); + lay->addSpacerItem(new QSpacerItem(40, 40, QSizePolicy::Expanding, QSizePolicy::Fixed)); + lay->addWidget(new QLabel("Settings files location ", this)); + QPushButton *navigateBtn = new QPushButton("Open", this); + scopy::StyleHelper::BlueButton(navigateBtn, "navigateBtn"); + navigateBtn->setMaximumWidth(80); + connect(navigateBtn, &QPushButton::clicked, this, + [=]() { QDesktopServices::openUrl(scopy::config::settingsFolderPath()); }); + lay->addWidget(navigateBtn); + return w; +} + +QWidget *PDKWindow::generalPreferences() +{ + QWidget *page = new QWidget(this); + QVBoxLayout *lay = new QVBoxLayout(page); + initGeneralPreferences(); + scopy::Preferences *p = scopy::Preferences::GetInstance(); + + lay->setMargin(0); + lay->setSpacing(10); + page->setLayout(lay); + + // General preferences + scopy::MenuSectionWidget *generalWidget = new scopy::MenuSectionWidget(page); + scopy::MenuCollapseSection *generalSection = + new scopy::MenuCollapseSection("General", scopy::MenuCollapseSection::MHCW_NONE, generalWidget); + generalWidget->contentLayout()->setSpacing(10); + generalWidget->contentLayout()->addWidget(generalSection); + generalSection->contentLayout()->setSpacing(10); + lay->addWidget(generalWidget); + lay->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); + + generalSection->contentLayout()->addWidget(buildSaveSessionPreference()); + generalSection->contentLayout()->addWidget(scopy::PreferencesHelper::addPreferenceCheckBox( + p, "general_save_attached", "Save/Load tool attached state", generalSection)); + generalSection->contentLayout()->addWidget(scopy::PreferencesHelper::addPreferenceCheckBox( + p, "general_doubleclick_attach", "Doubleclick to attach/detach tool", generalSection)); + generalSection->contentLayout()->addWidget(scopy::PreferencesHelper::addPreferenceCheckBox( + p, "general_doubleclick_ctrl_opens_menu", "Doubleclick control buttons to open menu", generalSection)); + generalSection->contentLayout()->addWidget(scopy::PreferencesHelper::addPreferenceCheckBox( + p, "general_use_opengl", "Enable OpenGL plotting", generalSection)); + generalSection->contentLayout()->addWidget(scopy::PreferencesHelper::addPreferenceCheckBox( + p, "general_use_animations", "Enable menu animations", generalSection)); + generalSection->contentLayout()->addWidget(scopy::PreferencesHelper::addPreferenceCheckBox( + p, "general_check_online_version", "Enable automatic online check for updates.", generalSection)); + generalSection->contentLayout()->addWidget(scopy::PreferencesHelper::addPreferenceCheckBox( + p, "general_show_status_bar", "Enable the status bar for displaying important messages.", + generalSection)); + generalSection->contentLayout()->addWidget( + scopy::PreferencesHelper::addPreferenceCheckBox(p, "show_grid", "Show Grid", generalSection)); + generalSection->contentLayout()->addWidget( + scopy::PreferencesHelper::addPreferenceCheckBox(p, "show_graticule", "Show Graticule", generalSection)); + generalSection->contentLayout()->addWidget(scopy::PreferencesHelper::addPreferenceCheckBox( + p, "iiowidgets_use_lazy_loading", "Use Lazy Loading", generalSection)); + generalSection->contentLayout()->addWidget(scopy::PreferencesHelper::addPreferenceCheckBox( + p, "plugins_use_debugger_v2", "Use Debugger V2 plugin", generalSection)); + generalSection->contentLayout()->addWidget(scopy::PreferencesHelper::addPreferenceCombo( + p, "general_theme", "Theme", {"default", "light"}, generalSection)); + + // Debug preferences + scopy::MenuSectionWidget *debugWidget = new scopy::MenuSectionWidget(page); + scopy::MenuCollapseSection *debugSection = + new scopy::MenuCollapseSection("Debug", scopy::MenuCollapseSection::MHCW_NONE, debugWidget); + debugWidget->contentLayout()->setSpacing(10); + debugWidget->contentLayout()->addWidget(debugSection); + debugSection->contentLayout()->setSpacing(10); + lay->addWidget(debugWidget); + lay->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); + + debugSection->contentLayout()->addWidget(scopy::PreferencesHelper::addPreferenceCheckBox( + p, "general_show_plot_fps", "Show plot FPS", debugSection)); + debugSection->contentLayout()->addWidget(scopy::PreferencesHelper::addPreferenceCombo( + p, "general_plot_target_fps", "Plot target FPS", {"15", "20", "30", "60"}, debugSection)); + + return page; +} + +void PDKWindow::initGeneralPreferences() +{ + scopy::Preferences *p = scopy::Preferences::GetInstance(); + p->setPreferencesFilename(PATH_TO_INI); + p->load(); + p->init("general_first_run", true); + p->init("general_save_session", true); + p->init("general_save_attached", true); + p->init("general_doubleclick_attach", true); +#if defined(__arm__) + p->init("general_use_opengl", false); +#else + p->init("general_use_opengl", true); +#endif + p->init("general_use_animations", true); + p->init("general_theme", "default"); + p->init("general_language", "en"); + p->init("show_grid", true); + p->init("show_graticule", false); + p->init("iiowidgets_use_lazy_loading", true); + p->init("plugins_use_debugger_v2", true); + p->init("general_plot_target_fps", "60"); + p->init("general_show_plot_fps", true); + p->init("general_use_native_dialogs", true); + p->init("general_additional_plugin_path", ""); + p->init("general_load_decoders", true); + p->init("general_doubleclick_ctrl_opens_menu", true); + p->init("general_check_online_version", false); + p->init("general_show_status_bar", true); +} + +void PDKWindow::initMainWindow() +{ + QWidget *centralWidget = new QWidget(this); + centralWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + centralWidget->setMinimumSize(1280, 720); + setCentralWidget(centralWidget); + QHBoxLayout *lay = new QHBoxLayout(centralWidget); + lay->setMargin(9); + lay->setSpacing(6); + + m_tabWidget = new QTabWidget(centralWidget); + m_tabWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + m_tabWidget->setTabPosition(QTabWidget::TabPosition::West); + scopy::StyleHelper::BackgroundPage(m_tabWidget, "pdkTable"); + + lay->addWidget(m_tabWidget); +} + +QWidget *PDKWindow::addHorizontalTab(QWidget *w, QLabel *lbl, bool tabEnabled) +{ + QWidget *pane = new QWidget(m_tabWidget); + pane->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + QHBoxLayout *lay = new QHBoxLayout(pane); + lay->setMargin(10); + pane->setLayout(lay); + + QScrollArea *scrollArea = new QScrollArea(pane); + scrollArea->setWidget(w); + scrollArea->setWidgetResizable(true); + scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + lay->addWidget(scrollArea); + + // Hackish - so we don't override paint event + int tabIdx = m_tabWidget->addTab(pane, ""); + m_tabWidget->setTabEnabled(tabIdx, tabEnabled); + + QTabBar *tabbar = m_tabWidget->tabBar(); + tabbar->setTabButton(tabbar->count() - 1, QTabBar::LeftSide, lbl); + tabbar->tabButton(tabbar->count() - 1, QTabBar::LeftSide)->setEnabled(tabEnabled); + return pane; +} +void PDKWindow::initPreferencesPage() +{ + m_prefPage = new QWidget(this); + QGridLayout *lay = new QGridLayout(m_prefPage); + lay->setSpacing(6); + lay->setMargin(0); + + scopy::MenuSectionWidget *generalWidget = new scopy::MenuSectionWidget(m_prefPage); + scopy::MenuCollapseSection *generalSection = new scopy::MenuCollapseSection( + "Scopy preferences", scopy::MenuCollapseSection::MHCW_NONE, generalWidget); + generalWidget->contentLayout()->setSpacing(10); + generalWidget->contentLayout()->addWidget(generalSection); + generalSection->contentLayout()->setSpacing(10); + generalSection->contentLayout()->addWidget(generalPreferences()); + + lay->addWidget(generalWidget, 0, 0); + lay->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 2, 0); +} + +void PDKWindow::addPluginPrefPage() +{ + QWidget *pluginPref = m_mainWidget->pluginPrefPage(); + if(pluginPref) { + QGridLayout *lay = dynamic_cast(m_prefPage->layout()); + if(!lay) + return; + scopy::MenuSectionWidget *pluginWidget = new scopy::MenuSectionWidget(m_prefPage); + scopy::MenuCollapseSection *pluginSection = new scopy::MenuCollapseSection( + "Plugin preferences", scopy::MenuCollapseSection::MHCW_NONE, pluginWidget); + pluginWidget->contentLayout()->setSpacing(10); + pluginWidget->contentLayout()->addWidget(pluginSection); + pluginSection->contentLayout()->setSpacing(10); + pluginSection->contentLayout()->addWidget(pluginPref); + lay->addWidget(pluginWidget, 1, 0); + } +} + +void PDKWindow::removePluginPrefPage() +{ + QGridLayout *lay = dynamic_cast(m_prefPage->layout()); + QLayoutItem *it = lay->itemAtPosition(1, 0); + if(!it) { + return; + } + QWidget *pluginPref = it->widget(); + if(pluginPref) { + m_prefPage->layout()->removeWidget(pluginPref); + delete pluginPref; + } +} + +QLabel *PDKWindow::createTabLabel(QString name) +{ + QLabel *lbl = new QLabel(); + scopy::StyleHelper::TabWidgetLabel(lbl, "tabWidgetLabel"); + lbl->setText(name); + return lbl; +} + +MainWidget::MainWidget(QWidget *parent) + : QWidget(parent) + , m_pluginManager(nullptr) +{ + m_state = State::Unloaded; + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + this->setMinimumWidth(1024); + QGridLayout *lay = new QGridLayout(this); + lay->setMargin(9); + lay->setSpacing(6); + + m_statusLbl = new QLabel(this); + scopy::StyleHelper::WarningLabel(m_statusLbl); + m_statusLbl->setWordWrap(true); + + // browse section + m_browseBtn = new QPushButton("Browse", this); + scopy::StyleHelper::BlueButton(m_browseBtn); + m_browseBtn->setFixedWidth(128); + m_browseBtn->setFixedHeight(40); + + m_pluginPathEdit = new QLineEdit(this); + m_pluginPathEdit->setText(PLUGIN_INSTALL_PATH); + m_pluginPathEdit->setPlaceholderText(PLUGIN_INSTALL_PATH); + connect(m_browseBtn, &QPushButton::clicked, this, [this]() { + browseFile(m_pluginPathEdit); + enableLoadConn(false); + }); + + // init + m_initBtn = new QPushButton("Init", this); + scopy::StyleHelper::BlueButton(m_initBtn); + m_initBtn->setFixedWidth(128); + m_initBtn->setFixedHeight(40); + connect(m_initBtn, &QPushButton::clicked, this, &MainWidget::onInit); + + // load btn + QWidget *loadBtns = new QWidget(this); + loadBtns->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + loadBtns->setLayout(new QVBoxLayout(loadBtns)); + loadBtns->layout()->setSpacing(0); + loadBtns->layout()->setMargin(0); + + m_loadBtn = new QPushButton("Load", this); + scopy::StyleHelper::BlueButton(m_loadBtn); + m_loadBtn->setFixedWidth(128); + m_loadBtn->setFixedHeight(40); + m_loadBtn->setEnabled(false); + connect(m_loadBtn, &QPushButton::clicked, this, &MainWidget::onLoad); + + m_unloadBtn = new QPushButton("Unload", this); + scopy::StyleHelper::BlueButton(m_unloadBtn); + m_unloadBtn->setFixedWidth(128); + m_unloadBtn->setFixedHeight(40); + m_unloadBtn->setVisible(false); + connect(m_unloadBtn, &QPushButton::clicked, this, &MainWidget::onUnload); + + loadBtns->layout()->addWidget(m_loadBtn); + loadBtns->layout()->addWidget(m_unloadBtn); + + // connect section + m_uriEdit = new QLineEdit(this); + m_uriEdit->setPlaceholderText("URI"); + m_uriEdit->setText("ip:127.0.0.1"); + + m_deviceTypeCb = new scopy::MenuCombo("category", this); + m_deviceTypeCb->setFixedHeight(40); + + QWidget *connBtns = new QWidget(this); + connBtns->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + connBtns->setLayout(new QVBoxLayout(connBtns)); + connBtns->layout()->setSpacing(0); + connBtns->layout()->setMargin(0); + + m_connBtn = new QPushButton("Connect", this); + scopy::StyleHelper::BlueButton(m_connBtn); + m_connBtn->setFixedWidth(128); + m_connBtn->setFixedHeight(40); + m_connBtn->setEnabled(false); + connect(m_connBtn, &QPushButton::clicked, this, &MainWidget::onConnect); + + m_disconnBtn = new QPushButton("Disconnect", this); + scopy::StyleHelper::BlueButton(m_disconnBtn); + m_disconnBtn->setFixedWidth(128); + m_disconnBtn->setFixedHeight(40); + m_disconnBtn->setVisible(false); + connect(m_disconnBtn, &QPushButton::clicked, this, &MainWidget::onDisconnect); + + connBtns->layout()->addWidget(m_connBtn); + connBtns->layout()->addWidget(m_disconnBtn); + + // plugin info + QWidget *pluginPage = new QWidget(this); + pluginPage->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + pluginPage->setLayout(new QVBoxLayout(pluginPage)); + pluginPage->layout()->setMargin(0); + + m_scrollArea = new QScrollArea(pluginPage); + m_scrollArea->setWidgetResizable(true); + m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + pluginPage->layout()->addWidget(m_scrollArea); + + m_pluginIcon = new QWidget(this); + m_pluginIcon->setLayout(new QHBoxLayout(m_pluginIcon)); + m_pluginIcon->layout()->setMargin(0); + m_pluginIcon->setFixedSize(100, 100); + + lay->addWidget(m_pluginPathEdit, 0, 0); + lay->addWidget(m_deviceTypeCb, 1, 0); + lay->addWidget(m_uriEdit, 2, 0); + lay->addWidget(m_statusLbl, 3, 0); + lay->addWidget(pluginPage, 4, 0); + + lay->addWidget(m_browseBtn, 0, 1, Qt::AlignTop); + lay->addWidget(m_initBtn, 1, 1, Qt::AlignTop); + lay->addWidget(loadBtns, 2, 1, Qt::AlignTop); + lay->addWidget(connBtns, 3, 1, Qt::AlignTop); + lay->addWidget(m_pluginIcon, 4, 1, Qt::AlignCenter | Qt::AlignBottom); +} + +MainWidget::~MainWidget() +{ + if(m_state == State::Connected) { + onDisconnect(); + } + if(m_state == State::Loaded) { + onUnload(); + } + if(!m_currentPlugin.isEmpty()) { + deinitialize(); + } +} + +QString MainWidget::pluginAbout() +{ + if(!m_pluginManager || !m_pluginManager->plugin()) + return ""; + return m_pluginManager->plugin()->about(); +} + +QWidget *MainWidget::pluginPrefPage() +{ + QWidget *prefPage = nullptr; + m_pluginManager->plugin()->initPreferences(); + if(m_pluginManager->plugin()->loadPreferencesPage()) + prefPage = m_pluginManager->plugin()->preferencesPage(); + + return prefPage; +} + +QList MainWidget::getPluginTools() { return m_pluginManager->plugin()->toolList(); } + +void MainWidget::onConnect() +{ + if(m_state == State::Unloaded) + onLoad(); + if(m_state != State::Loaded) + return; + if(!m_pluginManager->plugin()->onConnect()) { + updateStatusLbl("Connection failed!"); + return; + } + changeVisibility(m_disconnBtn, m_connBtn); + enableBrowseInit(false); + m_unloadBtn->setEnabled(false); + m_state = State::Connected; + updateStatusLbl(""); + Q_EMIT connected(); +} + +void MainWidget::onDisconnect() +{ + m_pluginManager->plugin()->onDisconnect(); + changeVisibility(m_disconnBtn, m_connBtn); + m_unloadBtn->setEnabled(true); + m_state = State::Loaded; + Q_EMIT disconnected(); +} + +void MainWidget::changeVisibility(QPushButton *btn1, QPushButton *btn2) +{ + btn1->setVisible(!btn1->isVisible()); + btn2->setVisible(!btn2->isVisible()); +} + +void MainWidget::enableBrowseInit(bool en) +{ + m_initBtn->setEnabled(en); + m_browseBtn->setEnabled(en); +} + +void MainWidget::enableLoadConn(bool en) +{ + m_loadBtn->setEnabled(en); + m_connBtn->setEnabled(en); +} + +void MainWidget::updateStatusLbl(QString msg) +{ + m_statusLbl->clear(); + m_statusLbl->setText(msg); +} + +void MainWidget::loadAvailCat() +{ + scopy::Plugin *plugin = m_pluginManager->plugin(); + if(plugin->metadata().isEmpty()) + return; + if(!plugin->metadata().contains("category")) // plugin metadata does not have category + return; + QJsonValue categoryVal = plugin->metadata().value("category"); + if(categoryVal.isString()) // single category + m_deviceTypeCb->combo()->addItem(categoryVal.toString()); + if(categoryVal.isArray()) { // list category + QJsonArray catArray = categoryVal.toArray(); + for(const auto &v : catArray) { + if(!v.isString()) { + continue; + } + m_deviceTypeCb->combo()->addItem(v.toString()); + } + } +} + +void MainWidget::deinitialize() +{ + if(m_pluginManager) { + QWidget *pluginIcon = m_pluginManager->plugin()->icon(); + if(pluginIcon) { + m_pluginIcon->layout()->removeWidget(pluginIcon); + delete pluginIcon; + } + } + m_deviceTypeCb->combo()->clear(); + deletePluginManager(); + Q_EMIT deinit(); +} + +void MainWidget::onInit() +{ + QString pluginPath = m_pluginPathEdit->text(); + if(pluginPath.compare(m_currentPlugin) == 0 && m_pluginManager) { + updateStatusLbl("The plugin is already initialized!"); + return; + } + deinitialize(); + m_pluginManager = new PluginManager(pluginPath, this); + if(!m_pluginManager->plugin()) { + enableLoadConn(false); + deletePluginManager(); + updateStatusLbl("The plugin couldn't be accessed! Path: " + pluginPath); + return; + } + if(m_pluginManager->plugin()->loadIcon()) { + m_pluginIcon->layout()->addWidget(m_pluginManager->plugin()->icon()); + } + m_pluginManager->plugin()->initMetadata(); + loadAvailCat(); + m_currentPlugin = pluginPath; + enableLoadConn(true); + updateStatusLbl(""); + Q_EMIT init(); +} + +void MainWidget::onLoad() +{ + QString uri = m_uriEdit->text(); + QString cat = m_deviceTypeCb->combo()->currentText(); + if(!validConnection(uri, cat) || !isCompatible(uri, cat)) { + return; + } + loadInfoPage(); + enableBrowseInit(false); + changeVisibility(m_unloadBtn, m_loadBtn); + m_state = State::Loaded; + updateStatusLbl(""); + m_deviceTypeCb->setEnabled(false); + m_uriEdit->setEnabled(false); + Q_EMIT loaded(); +} + +void MainWidget::onUnload() +{ + m_pluginManager->plugin()->unload(); + unloadInfoPage(); + enableBrowseInit(true); + changeVisibility(m_unloadBtn, m_loadBtn); + m_state = State::Unloaded; + m_deviceTypeCb->setEnabled(true); + m_uriEdit->setEnabled(true); + Q_EMIT unloaded(); +} + +void MainWidget::browseFile(QLineEdit *pluginPathEdit) +{ + QString filePath = + QFileDialog::getOpenFileName(this, "Open a file", "directoryToOpen", + "All (*);;XML Files (*.xml);;Text Files (*.txt);;BIN Files (*.bin)"); + pluginPathEdit->setText(filePath); +} + +void MainWidget::deletePluginManager() +{ + if(m_pluginManager) { + delete m_pluginManager; + m_pluginManager = nullptr; + } +} + +void MainWidget::unloadInfoPage() +{ + QWidget *pluginPage = m_pluginManager->plugin()->page(); + if(pluginPage) { + m_scrollArea->takeWidget(); + } +} + +void MainWidget::loadInfoPage() +{ + if(m_pluginManager->plugin()->loadPage()) { + m_scrollArea->setWidget(m_pluginManager->plugin()->page()); + } +} + +bool MainWidget::validConnection(QString uri, QString cat) +{ + ConnectionStrategy *connStrategy = new ConnectionStrategy(uri, this); + bool validConn = false; + validConn = connStrategy->validConnection(cat); + if(!validConn) { + updateStatusLbl("Cannot connect to URI!"); + } + connStrategy->deleteLater(); + return validConn; +} + +bool MainWidget::isCompatible(QString uri, QString cat) +{ + bool compatible = false; + compatible = m_pluginManager->pluginCompatibility(uri, cat); + if(!compatible) { + updateStatusLbl("The plugin is not compatible with the device or doesn't exist!"); + } + return compatible; +} + +PluginManager::PluginManager(QString pluginPath, QObject *parent) + : QObject(parent) + , m_loaded(false) + , m_plugin(nullptr) +{ + loadPlugin(pluginPath); +} + +PluginManager::~PluginManager() +{ + if(m_plugin) { + delete m_plugin; + m_plugin = nullptr; + } +} + +void PluginManager::initPlugin() +{ + if(!m_plugin || m_loaded) + return; + m_plugin->preload(); + m_plugin->init(); + m_plugin->loadToolList(); + m_plugin->loadExtraButtons(); + m_plugin->postload(); + m_loaded = true; +} + +bool PluginManager::pluginCompatibility(QString param, QString category) +{ + initPlugin(); + if(!m_plugin->compatible(param, category)) + return false; + m_plugin->setParam(param, category); + m_plugin->setEnabled(true); + return true; +} + +scopy::Plugin *PluginManager::plugin() const { return m_plugin; } + +void PluginManager::loadPlugin(QString file) +{ + bool ret; + scopy::Plugin *original = nullptr; + scopy::Plugin *clone = nullptr; + + if(!QFile::exists(file)) + return; + + if(!QLibrary::isLibrary(file)) + return; + + QPluginLoader qp(file); + ret = qp.load(); + if(!ret) { + qWarning() << "Cannot load library " + qp.fileName() + "- err: " + qp.errorString(); + return; + } + + QObject *inst = qp.instance(); + if(!inst) { + qWarning() << "Cannot create QObject instance from loaded library"; + return; + } + + original = qobject_cast(qp.instance()); + if(!original) { + qWarning() << "Loaded library instance is not a Plugin*"; + return; + } + + clone = original->clone(this); + if(!clone) { + qWarning() << "clone method does not clone the object"; + return; + } + + QString cloneName; + cloneName = clone->name(); + + if(cloneName == "") + return; + + m_plugin = clone; +} + +ConnectionStrategy::ConnectionStrategy(QString uri, QObject *parent) + : m_uri(uri) + , QObject(parent) +{} + +ConnectionStrategy::~ConnectionStrategy() {} + +bool ConnectionStrategy::validConnection(QString cat) +{ + bool valid = false; + if(cat.compare("iio") == 0) { + valid = iioConn(); + } else { + valid = testConn(); + } + return valid; +} + +bool ConnectionStrategy::iioConn() +{ + iio_context *ctx = iio_create_context_from_uri(m_uri.toStdString().c_str()); + if(!ctx) { + return false; + } + iio_context_destroy(ctx); + return true; +} + +bool ConnectionStrategy::testConn() { return true; }