diff --git a/CbersApp.pro b/CbersApp.pro
new file mode 100644
index 0000000..3863783
--- /dev/null
+++ b/CbersApp.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+SUBDIRS = CbersUI x3py CbersPluginCore CbersApp plugins
+CbersApp.depends = CbersUI CbersPluginCore plugins
+CbersPluginCore.depends = x3py
+plugins.depends = CbersPluginCore
diff --git a/CbersApp/CbersApp.ico b/CbersApp/CbersApp.ico
new file mode 100644
index 0000000..c693aaf
Binary files /dev/null and b/CbersApp/CbersApp.ico differ
diff --git a/CbersApp/CbersApp.pro b/CbersApp/CbersApp.pro
new file mode 100644
index 0000000..287af34
--- /dev/null
+++ b/CbersApp/CbersApp.pro
@@ -0,0 +1,116 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2016-09-08T16:10:14
+#
+#-------------------------------------------------
+
+QT += core gui opengl xml
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+TARGET = CbersApp
+TEMPLATE = app
+
+{
+ CONFIG(debug, debug|release){
+ TARGET = $$join(TARGET,,,d)
+
+ DESTDIR = $$PWD/../bin/debug
+ }
+ else{
+ DESTDIR = $$PWD/../bin/release
+ }
+}
+
+
+SOURCES += main.cpp\
+ mainwindow.cpp \
+ pluginmanager.cpp \
+ ribbonpluginmanager.cpp
+
+HEADERS += mainwindow.h \
+ pluginmanager.h \
+ ribbonpluginmanager.h
+
+FORMS += mainwindow.ui
+
+
+CONFIG(release, debug|release): LIBS += -L$$PWD/../lib/release/ -lCbersUI
+else:CONFIG(debug, debug|release): LIBS += -L$$PWD/../lib/debug/ -lCbersUId
+
+unix{
+ LIBS += -ldl
+}
+
+INCLUDEPATH += $$PWD/../include
+INCLUDEPATH += $$PWD/../include/CbersUI
+INCLUDEPATH += $$PWD/../include/x3py
+INCLUDEPATH += $$PWD/../include/PluginCore
+DEPENDPATH += $$PWD/../include
+DEPENDPATH += $$PWD/../include/CbersUI
+DEPENDPATH += $$PWD/../include/x3py
+DEPENDPATH += $$PWD/../include/PluginCore
+
+win32{
+ LIBS += -lDbghelp
+}
+
+SDK_PATH = $$PWD/../
+
+win32{
+ RC_FILE= CbersApp_win32.rc
+}
+
+RESOURCES += \
+ CbersApp.qrc
+
+TRANSLATION_DIR = $$PWD/../i18n/
+TRANSLATIONS = $$TRANSLATION_DIR/CbersApp_zh_CN.ts
+
+# Copies the given files to the destination directory
+defineReplace(copyToDir) {
+ files = $$1
+ DIR = $$2
+ SRCDIR = $$3
+ LINK =
+
+ win32:DIR ~= s,/,\\,g
+ win32{
+ LINK += if not exist $$quote($$DIR) ( $$QMAKE_MKDIR $$quote($$DIR) ) $$escape_expand(\\n\\t)
+ }
+ unix{
+ LINK += $$QMAKE_MKDIR $$quote($$DIR) $$escape_expand(\\n\\t)
+ }
+ for(FILE, files) {
+ !isEmpty(SRCDIR){
+ FILE = $$SRCDIR/$$FILE
+ }
+ win32:FILE ~= s,/,\\,g
+ LINK += $$QMAKE_COPY $$quote($$FILE) $$quote($$DIR) $$escape_expand(\\n\\t)
+ }
+ return($$LINK)
+}
+
+win32{
+ QMAKE_POST_LINK += cd $$quote($$PWD) $$escape_expand(\\n\\t)
+}
+unix{
+ QMAKE_POST_LINK += cd $$quote($$PWD) $$escape_expand(\\n\\t)
+}
+
+# Auto Update And Release TRANSLATIONS
+win32:TRANSLATION_DIR ~= s,/,\\,g
+win32{
+ QMAKE_POST_LINK += if not exist $$quote($$TRANSLATION_DIR) ( $$QMAKE_MKDIR $$quote($$TRANSLATION_DIR) ) $$escape_expand(\\n\\t)
+}
+unix{
+ QMAKE_POST_LINK += $$QMAKE_MKDIR -p $$quote($$TRANSLATION_DIR) $$escape_expand(\\n\\t)
+}
+
+QMAKE_POST_LINK += $(QTDIR)/bin/lupdate $$PWD/CbersApp.pro $$escape_expand(\\n\\t)
+QMAKE_POST_LINK += $(QTDIR)/bin/lrelease $$PWD/CbersApp.pro $$escape_expand(\\n\\t)
+RELEASE_TRANSLATIONS = $$TRANSLATIONS
+RELEASE_TRANSLATIONS ~= s,.ts,.qm,g
+QMAKE_POST_LINK += $$copyToDir($$RELEASE_TRANSLATIONS, $$DESTDIR/i18n/)
diff --git a/CbersApp/CbersApp.qrc b/CbersApp/CbersApp.qrc
new file mode 100644
index 0000000..15ac2ad
--- /dev/null
+++ b/CbersApp/CbersApp.qrc
@@ -0,0 +1,5 @@
+
+
+ CbersApp.ico
+
+
diff --git a/CbersApp/CbersApp_win32.rc b/CbersApp/CbersApp_win32.rc
new file mode 100644
index 0000000..8338870
--- /dev/null
+++ b/CbersApp/CbersApp_win32.rc
@@ -0,0 +1,36 @@
+#include "winver.h"
+
+IDI_ICON1 ICON "CbersApp.ico"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x0L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "080404b0"
+ BEGIN
+ VALUE "CompanyName", "CbersApp"
+ VALUE "FileDescription", "CbersApp"
+ VALUE "FileVersion", "1.0.0.1"
+ VALUE "InternalName", "CbersApp.exe"
+ VALUE "LegalCopyright", "Copyright (C) 2018"
+ VALUE "OriginalFilename", "CbersApp.exe"
+ VALUE "ProductName", "CbersApp"
+ VALUE "ProductVersion", "1.0.0.1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x804, 1200
+ END
+END
\ No newline at end of file
diff --git a/CbersApp/main.cpp b/CbersApp/main.cpp
new file mode 100644
index 0000000..ca83ca4
--- /dev/null
+++ b/CbersApp/main.cpp
@@ -0,0 +1,91 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "mainwindow.h"
+#include "pluginmanager.h"
+#include "x3py/observer/observerimpl.h"
+
+int main(int argc, char *argv[])
+{
+ QString configpath = QFileInfo(QString::fromLocal8Bit(argv[0])).absolutePath() + "/config";
+ QSettings::setDefaultFormat( QSettings::IniFormat );
+ QSettings::setPath( QSettings::IniFormat, QSettings::UserScope, configpath);
+
+ QApplication a(argc, argv);
+ a.setWindowIcon(QIcon(":/CbersApp.ico"));
+
+ QCoreApplication::setOrganizationName( QObject::tr("CbersApp") );
+ QCoreApplication::setOrganizationDomain( QObject::tr("CbersApp") );
+ QCoreApplication::setApplicationName( QObject::tr("CbersApp") );
+ QCoreApplication::setAttribute( Qt::AA_DontShowIconsInMenus, false );
+
+ QSettings mySettings;
+ //////////////////////////////////////////////////////////////
+ // Load Translator
+ QString i18nPath = QApplication::applicationDirPath() + "/i18n";
+ QString myUserLocale = mySettings.value( "locale/userLocale", "" ).toString();
+ bool myLocaleOverrideFlag = mySettings.value( "locale/overrideFlag", false ).toBool();
+ QString myTranslationCode;
+ if ( !myTranslationCode.isNull() && !myTranslationCode.isEmpty() )
+ {
+ mySettings.setValue( "locale/userLocale", myTranslationCode );
+ }
+ else
+ {
+ if ( !myLocaleOverrideFlag || myUserLocale.isEmpty() )
+ {
+ myTranslationCode = QLocale::system().name();
+ mySettings.setValue( "locale/userLocale", myTranslationCode );
+ }
+ else
+ {
+ myTranslationCode = myUserLocale;
+ }
+ }
+
+ QTranslator apptor( 0 );
+ QTranslator cbersUItor( 0 );
+ QTranslator qttor( 0 );
+ if ( myTranslationCode != "C" )
+ {
+ if ( apptor.load( QString( "CbersApp_" ) + myTranslationCode, i18nPath ) )
+ {
+ a.installTranslator( &apptor );
+ }
+ else
+ {
+ qWarning( "loading of CbersApp translation failed [%s]", QString( "%1/CbersApp_%2" ).arg( i18nPath ).arg( myTranslationCode ).toLocal8Bit().constData() );
+ }
+
+ if ( cbersUItor.load( QString( "CbersUI_" ) + myTranslationCode, i18nPath ) )
+ {
+ a.installTranslator( &cbersUItor );
+ }
+ else
+ {
+ qWarning( "loading of CbersUI translation failed [%s]", QString( "%1/CbersUI_%2" ).arg( i18nPath ).arg( myTranslationCode ).toLocal8Bit().constData() );
+ }
+
+ if ( qttor.load( QString( "qt_" ) + myTranslationCode, i18nPath ) )
+ {
+ a.installTranslator( &qttor );
+ }
+ else
+ {
+ qWarning( "loading of qt translation failed [%s]", QString( "%1_%2" ).arg( i18nPath ).arg( myTranslationCode ).toLocal8Bit().constData() );
+ }
+ }
+ //////////////////////////////////////////////////////////////
+
+ if( !CPluginManager::Initialize("CbersPlugins") )
+ return -1;
+
+ MainWindow w;
+ w.showMaximized();
+
+ return a.exec();
+}
diff --git a/CbersApp/mainwindow.cpp b/CbersApp/mainwindow.cpp
new file mode 100644
index 0000000..212059b
--- /dev/null
+++ b/CbersApp/mainwindow.cpp
@@ -0,0 +1,67 @@
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include
+#include
+#include "ribbonpluginmanager.h"
+#include "qribbonstylesheetmanager.h"
+
+MainWindow::MainWindow(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::MainWindow)
+{
+ setObjectName("QRibbonMainWindow");
+ setWindowFlags( Qt::FramelessWindowHint );
+ ui->setupUi(this);
+
+ mRibbonBar = new QRibbonBar(this->centralWidget());
+
+ mMdiArea = new QMdiArea(this->centralWidget());
+ //mMdiArea->setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
+ mMdiArea->setViewMode(QMdiArea::SubWindowView);
+ //mMdiArea->setViewMode(QMdiArea::TabbedView);
+ mMdiArea->setTabShape(QTabWidget::Rounded);
+ mMdiArea->setTabPosition(QTabWidget::North);
+ connect(mMdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(subWindowActivated(QMdiSubWindow *)));
+
+ CRibbonPluginManager::getInstance()->Create(this, mRibbonBar, mMdiArea);
+ setMenuWidget(mRibbonBar);
+ setCentralWidget(mMdiArea);
+
+ QRibbonStyleSheetManager::instance()->applyStyleSheet("office2007_black");
+ //registerHandlers();
+}
+
+MainWindow::~MainWindow()
+{
+ CRibbonPluginManager::getInstance()->DestroyControl();
+
+ if( mRibbonBar!=nullptr )
+ delete mRibbonBar;
+ mRibbonBar = nullptr;
+
+ delete ui;
+}
+
+bool MainWindow::OnAnything(x3::IObject* sender, const std::string& eventKey, const QVariant& wParam, const QVariant& lParam)
+{
+ //if( _stricmp(eventKey.c_str(), "scaleChanged")==0 )
+ //{
+ //}
+ return true;
+}
+
+void MainWindow::subWindowActivated(QMdiSubWindow* pSubWindow)
+{
+ if( pSubWindow==Q_NULLPTR )
+ return;
+
+ QVariant vtData = pSubWindow->property("IUIPlugin");
+ if( !vtData.isValid() )
+ return;
+
+ x3::Object spCommon((IUIPlugin*)(vtData.toLongLong()));
+ if( !spCommon.valid() )
+ return;
+
+ CRibbonPluginManager::getInstance()->SetViewer(spCommon.p());
+}
diff --git a/CbersApp/mainwindow.h b/CbersApp/mainwindow.h
new file mode 100644
index 0000000..c699665
--- /dev/null
+++ b/CbersApp/mainwindow.h
@@ -0,0 +1,44 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "qribbonbar.h"
+USING_NAMESPACE_CBERSUI
+
+#include "UIPluginsEvents.h"
+USING_NAMESPACE_CBERSPLUGINS
+
+namespace Ui {
+class MainWindow;
+}
+
+class MainWindow : public QMainWindow, public IAnythingEventObserver
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+
+public:
+ // IAnythingEventObserver
+ virtual bool OnAnything(x3::IObject* sender, const std::string& eventKey, const QVariant& wParam, const QVariant& lParam);
+
+protected slots:
+ void subWindowActivated(QMdiSubWindow *);
+
+private:
+ Ui::MainWindow *ui;
+ QRibbonBar* mRibbonBar;
+ QMdiArea* mMdiArea;
+};
+
+#endif // MAINWINDOW_H
diff --git a/CbersApp/mainwindow.ui b/CbersApp/mainwindow.ui
new file mode 100644
index 0000000..3d7e2b4
--- /dev/null
+++ b/CbersApp/mainwindow.ui
@@ -0,0 +1,22 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ MainWindow
+
+
+
+
+
+
+
+
diff --git a/CbersApp/pluginmanager.cpp b/CbersApp/pluginmanager.cpp
new file mode 100644
index 0000000..5ea1f08
--- /dev/null
+++ b/CbersApp/pluginmanager.cpp
@@ -0,0 +1,269 @@
+#include "pluginmanager.h"
+#include "x3py/nonplugin/scanplugins.h"
+#include "x3py/manager/x3manager.h"
+#include "x3py/manager/iplugins.h"
+
+int CPluginManager::MINID = 3000;
+int CPluginManager::MAXID = 3999;
+
+CPluginManager::CPluginManager(void)
+{
+ m_nNextID = MINID;
+ m_nLastTool = -1;
+}
+
+CPluginManager::~CPluginManager(void)
+{
+ UnloadPlugins();
+}
+
+bool CPluginManager::Initialize(const char* folder)
+{
+ return x3::loadScanPlugins(folder)>0;
+}
+
+bool CPluginManager::UnInitialize()
+{
+ x3::unloadScanPlugins();
+ return true;
+}
+
+bool CPluginManager::LoadPlugins()
+{
+ UnloadPlugins();
+
+ x3::Object spPlugins(x3::clsidManager);
+ if( !spPlugins.valid() || spPlugins->getPluginCount()<=0 )
+ return false;
+
+ x3::Object spUICore(clsidUICore);
+ x3::LockRW lockcls(m_mapPlugin.locker, true);
+ bool ret = false;
+ if( lockcls.canWrite() )
+ {
+ int nCount = spPlugins->getCLSIDCount();
+ for( int i=0; igetCLSID(i);
+ if( clsid==NULL )
+ continue;
+
+ x3::Object spCommon(clsid);
+ if( !spCommon.valid() )
+ continue;
+
+ if( !spCommon->Initialize() )
+ continue;
+
+ if( spUICore.valid() )
+ spUICore->Add(spCommon->getClassName(), spCommon.p());
+
+ x3::Object spView = spCommon;
+ if( spView.valid() )
+ m_mapView.push_back(spView.p());
+ else
+ {
+ int nNextID = GetNextID();
+ if( nNextID==-1 )
+ break;
+
+ m_mapPlugin[nNextID] = spCommon.p();
+ }
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+
+bool CPluginManager::UnloadPlugins()
+{
+ x3::Object spUICore(clsidUICore);
+ x3::LockRW lockcls(m_mapPlugin.locker, true);
+ if( lockcls.canWrite() )
+ {
+ hash_map::iterator it = m_mapPlugin.begin();
+ for( ; it!=m_mapPlugin.end(); it++ )
+ {
+ if( it->second.valid() )
+ {
+ x3::Object spCommond(it->second);
+ if( spCommond.valid() )
+ {
+ if( spUICore.valid() )
+ spUICore->Remove(spCommond->getClassName());
+ spCommond->UnInitialize();
+ }
+ }
+ }
+ m_mapPlugin.clear();
+ m_nNextID = MINID;
+ m_nLastTool = -1;
+
+ x3::LockRW lockcls2(m_mapIdleID.locker, true);
+ if( lockcls2.canWrite() )
+ m_mapIdleID.clear();
+ }
+
+ {
+ x3::LockRW lockcls(m_mapView.locker, true);
+ if( lockcls.canWrite() )
+ {
+ std::vector::iterator it = m_mapView.begin();
+ for( ; it!=m_mapView.end(); it++ )
+ {
+ if( (*it).valid() )
+ {
+ x3::Object spCommond(*it);
+ if( spCommond.valid() )
+ {
+ if( spUICore.valid() )
+ spUICore->Remove(spCommond->getClassName());
+ spCommond->UnInitialize();
+ }
+ }
+ }
+ m_mapView.clear();
+ }
+ }
+
+ return true;
+}
+
+int CPluginManager::GetNextID()
+{
+ x3::LockRW lockcls(m_mapIdleID.locker, true);
+ int ret = -1;
+ if( lockcls.canWrite() )
+ {
+ std::vector::iterator it = m_mapIdleID.begin();
+ if( it!=m_mapIdleID.end() )
+ {
+ ret = *it;
+ m_mapIdleID.erase(it);
+ }
+ }
+
+ if( ret!=-1 )
+ return ret;
+
+ if( m_nNextID>MAXID )
+ return ret;
+
+ ret = m_nNextID++;
+ return ret;
+}
+
+void CPluginManager::FreeID(int id)
+{
+ if( id==m_nLastTool )
+ m_nLastTool = -1;
+
+ if( idMAXID || id>=m_nNextID )
+ return;
+
+ x3::LockRW lockcls(m_mapIdleID.locker, true);
+ if( lockcls.canWrite() )
+ {
+ std::vector::iterator it = m_mapIdleID.begin();
+ for( ; it!=m_mapIdleID.end(); it++ )
+ {
+ if( *it==id )
+ return;
+ }
+
+ m_mapIdleID.push_back(id);
+ }
+}
+
+int CPluginManager::GetViewPluginCount()
+{
+ x3::LockRW lockcls(m_mapView.locker);
+ int ret = 0;
+ if( lockcls.canRead() )
+ ret = m_mapView.size();
+
+ return ret;
+}
+
+bool CPluginManager::GetViewPlugin(int index, IUIView** ppIView)
+{
+ x3::LockRW lockcls(m_mapView.locker);
+ IUIView* ret = nullptr;
+ if( lockcls.canRead() )
+ {
+ if( index>=0 && index::iterator it = m_mapView.begin() + index;
+ if( it!=m_mapView.end() )
+ {
+ x3::Object spCommon(*it);
+ ret = spCommon.p();
+ }
+ }
+ }
+
+ return ret;
+}
+
+int CPluginManager::GetPluginCount()
+{
+ x3::LockRW lockcls(m_mapPlugin.locker);
+ int ret = 0;
+ if( lockcls.canRead() )
+ ret = m_mapPlugin.size();
+
+ return ret;
+}
+
+IUIPlugin* CPluginManager::FindPlugin(int id)
+{
+ x3::LockRW lockcls(m_mapPlugin.locker);
+ IUIPlugin* ret = nullptr;
+ if( lockcls.canRead() )
+ {
+ hash_map::iterator it = m_mapPlugin.find(id);
+ if( it!=m_mapPlugin.end() )
+ {
+ x3::Object spCommon(it->second);
+ ret = spCommon.p();
+ }
+ }
+
+ return ret;
+}
+
+bool CPluginManager::GetPlugin(int index, int& id, IUIPlugin** ppICommon)
+{
+ if( ppICommon==NULL )
+ return false;
+
+ x3::LockRW lockcls(m_mapPlugin.locker);
+ bool ret = false;
+ if( lockcls.canRead() )
+ {
+ if( index>=0 && index::iterator it = m_mapPlugin.begin();
+ for( int i=0; ifirst;
+ if( *ppICommon!=NULL )
+ {
+ (*ppICommon)->releaseObject();
+ *ppICommon = NULL;
+ }
+
+ x3::Object spCommon(it->second);
+ *ppICommon = spCommon.p();
+ if( *ppICommon!=NULL )
+ ret = true;
+ }
+ }
+ }
+
+ return ret;
+}
diff --git a/CbersApp/pluginmanager.h b/CbersApp/pluginmanager.h
new file mode 100644
index 0000000..d162c5c
--- /dev/null
+++ b/CbersApp/pluginmanager.h
@@ -0,0 +1,51 @@
+#ifndef CPLUGINMANAGER_H
+#define CPLUGINMANAGER_H
+#include "x3py/module/plugininc.h"
+#include "x3py/objptr.h"
+#include "x3py/utilfunc/lockrw.h"
+#include "UIPlugins.h"
+USING_NAMESPACE_CBERSPLUGINS
+
+#include