当前位置: 首页 > 工具软件 > QCAD > 使用案例 >

QCad源码分析 第一章

段干博涉
2023-12-01

   鉴于介绍Qcad相关的文章很少,决定写此博客,一来便于日后查找,二来要有分享精神。本文章基于Qcad3 .21.3.4的开源版本进行分析,分过程中难免有疏漏,如果有新的发现会及时更改,不足之处望高手指正,十分感谢。

   QCad是一款2维的cad软件,基于Qt类库开发,逻辑处理方面夹杂着QtScript,所以首先要熟悉javascript,js相关文章不在赘述,其次QtScript的使用方面,详细阅读Qt官方文档Qt Script。

    首先讲一下QCad软件中的简单启动过程,也就是代码中的main函数,QCad是一款跨平台的软件,暂时之讲解window平台的源码。

int main(int argc, char *argv[]) {
    qDebug() << "QCAD version " << R_QCAD_VERSION_STRING;
    // For correct Unicode translation, apply the current system locale:
    setlocale(LC_ALL, "");
    // But use usual conversion for scanf()/sprintf():
    setlocale(LC_NUMERIC, "C");

    // Finetuning Japanese encoding for correct DXF/DWG import.
    // see http://qt-project.org/doc/qt-4.8/codecs-jis.html
#ifdef Q_OS_WIN
    _putenv_s("UNICODEMAP_JP", "cp932");
#else
    setenv("UNICODEMAP_JP", "cp932", 1);
#endif

#ifdef Q_OS_WIN
#if QT_VERSION >= 0x050200
    // enable OpenGL logging under Windows
    // this info can then be shown in the about dialog
    QLoggingCategory::setFilterRules(QStringLiteral("qt.qpa.gl=true"));
#endif
#endif

    // Auto scale up user interface for high res displays under Windows:
#ifdef Q_OS_WIN
#if QT_VERSION >= 0x050600
    //_putenv_s("QT_SCALE_FACTOR", "auto");
    _putenv_s("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
#else
    _putenv_s("QT_DEVICE_PIXEL_RATIO", "auto");
#endif
#endif

#ifdef Q_OS_MAC
    // TODO: fix linking with objective c
    removeMacMenus();
#endif

    // these are defaults:
    //添加组织、公司、版本信息
    qApp->setOrganizationName("QCAD");
    qApp->setOrganizationDomain("QCAD.org");
    qApp->setApplicationName("QCAD");
    qApp->setApplicationVersion(RSettings::getVersionString());

    //调试输出重定义
    RMainWindow::installMessageHandler();

#if QT_VERSION >= 0x050000
    //高像素比
    QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif

#ifdef Q_OS_MAC
    // TODO: make available as script function:
    QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus);

    if (QSysInfo::MacintoshVersion>=0x000B) {
        // system font change bug fix on OS X 10.9 (Mavericks):
        QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
    }
#endif

    //产生随机数
    QTime time = QTime::currentTime();
    qsrand((uint)time.msec());

    //设置原始参数到RSettings当中
    QStringList originalArguments;
    for (int i=0; i<argc; i++) {
        QString a = argv[i];
        originalArguments.append(a);
    }
    RSettings::setOriginalArguments(originalArguments);

    //得到应用程序的id,用于一个终端只能启用一个QCad程序
    QString appId = "QCAD";
    for (int i=0; i<argc; i++) {
        QString a = argv[i];
        if (a=="-app-id" && i+1<argc) {
            appId = argv[i+1];
        }
    }

    //是否启用帮助界面
    bool guiEnabled = true;
    for (int i=1; i<argc; i++) {
        if (!strcmp(argv[i], "-no-gui") || !strcmp(argv[i], "-help")) {
            //如果设置-no-gui或者-help参数,则不启用界面
            guiEnabled = false;
        }
    }

    //应用程序的派生类,派生主要用于一个终端只能启用一个QCad程序中的本地服务通信
    RSingleApplication* app = new RSingleApplication(appId, argc, argv, guiEnabled);

#if defined(Q_OS_MAC) || defined(Q_OS_LINUX)
    // note that SIGPIPE is only ignored in release mode, gdb catches SIGPIPE
    // by default. To disable that behavior in gdb, use:
    // handle SIGPIPE nostop noprint pass
    signal(SIGPIPE,catchSigPipe);
#endif

#ifdef Q_OS_MAC
    // activate Mac OS X dock icon if desired:
    if (!app->arguments().contains("-no-dock-icon") &&
            !app->arguments().contains("-help") && !app->arguments().contains("-h") &&
            !app->arguments().contains("-version") && !app->arguments().contains("-v")) {
        ProcessSerialNumber psn;
        if (GetCurrentProcess(&psn) == noErr) {
            TransformProcessType(&psn, kProcessTransformToForegroundApplication);
        }
    }
#endif
    if (!app->arguments().contains("-allow-multiple-instances")) {
        //如果进程不允许多实例
        // send arguments to running instance for further processing:
        if (app->sendMessage(app->arguments().join("\n"), 30000)) {
            qWarning("Application already running. Aborting...");
            return 0;
        }
    }

#ifdef Q_OS_WIN
    // SVG icons are only rendered if this line is present under windows:
    QImageReader::supportedImageFormats();

    // the SQLite plugin can only be loaded if this line is present under windows:
    QSqlDatabase::drivers();
#endif

    //注册RColor类型到元对象系统
    qRegisterMetaType<RColor>();
    //将RColor注册到流操纵当中去,RColor支持<<操作
    qRegisterMetaTypeStreamOperators<RColor>("RColor");

    //注册RVector类型到元对象系统
    qRegisterMetaType<RVector>();
    //将RColor注册到流操纵当中去,RVector支持<<操作
    qRegisterMetaTypeStreamOperators<RVector>("RVector");

    //获取当前路径
    QString cwd = QDir::currentPath();
    //设置发布路径
    RSettings::setLaunchPath(cwd);

    // set current working directory:
    //将应用程序所在的目录设为当前目录
    QDir::setCurrent(RSettings::getApplicationPath());

    // disable Qt library paths to avoid plugins for Qt designer from being found:
    QStringList pluginPaths = RSettings::getPluginPaths();
    if (pluginPaths.isEmpty()) {
        qWarning() << "No plugin paths found";
        return -1;
    }
    //设置库路径,查找dll时将在此目录下查找
    app->setLibraryPaths(pluginPaths);
    //数学库
    RMath::init();
    //加载字体
    RFontList::init();
    //加载填充图形
    RPatternListMetric::init();
    RPatternListImperial::init();

    // init object properties:
    //初始化对象属性id
    RObject::init();
    REntity::init();
    RDocumentVariables::init();

    RArcEntity::init();
    RBlockReferenceEntity::init();
    RCircleEntity::init();
    RDimensionEntity::init();
    RDimLinearEntity::init();
    RDimAlignedEntity::init();
    RDimAngularEntity::init();
    RDimAngular2LEntity::init();
    RDimAngular3PEntity::init();
    RDimArcLengthEntity::init();
    RDimDiametricEntity::init();
    RDimOrdinateEntity::init();
    RDimRadialEntity::init();
    RDimRotatedEntity::init();
    REllipseEntity::init();
    RImageEntity::init();
    RHatchEntity::init();
    RLeaderEntity::init();
    RLineEntity::init();
    RPointEntity::init();
    RPolylineEntity::init();
    RSolidEntity::init();
    RTraceEntity::init();
    RFaceEntity::init();
    RSplineEntity::init();
    RXLineEntity::init();
    RRayEntity::init();
    RViewportEntity::init();

    RTextBasedEntity::init();
    RTextEntity::init();
    RAttributeDefinitionEntity::init();
    RAttributeEntity::init();

    RUcs::init();
    RLayer::init();
    RLayout::init();
    RLinetype::init();
    RBlock::init();
    RView::init();

    // make sure plugins can find plugin related settings:
    // these are always stored in "QCAD3.ini/conf":
    //重载应用程序名称【】
    RSettings::setApplicationNameOverride("QCAD3");
    //插件管理类
    RPluginLoader::loadPlugins(true);
    //初始化线型文件
    RLinetypeListMetric::init();
    RLinetypeListImperial::init();

    // check for autostart option:
    //检查自动脚本选项
    QString autostartFile;
    //获取参数列表,并从参数列表中查找是否有启动的脚本文件
    QStringList arguments = app->arguments();
    int i = arguments.indexOf("-autostart");
    if (i!=-1 && arguments.count()>i+1) {
        autostartFile = arguments.at(i+1);
    }

    //将脚本的工厂函数和脚本类型注册到系统当中,【jsfactory--js, pytonfactory--python】
    RScriptHandlerRegistry::registerScriptHandler(RScriptHandlerEcma::factory,
            RScriptHandlerEcma::getSupportedFileExtensionsStatic());
    //通过脚本工厂【jsfactory】创建具体的脚本类
    RScriptHandler* handler = RScriptHandlerRegistry::getGlobalScriptHandler("js");
    Q_ASSERT(handler!=NULL);
    //初始化自动脚本程序【初始化过程中会创建主界面】
    handler->init(autostartFile, arguments.mid(i+1));

    //如果脚本初始化过程中出现异常,则返回
    int ret = 0;
    if (handler->hasUncaughtExceptions()) {
        ret = 1;
    }

    // delete script handler and print uncaught exceptions:
    //删除脚本句柄,打印异常
    delete handler;

    
    RPluginLoader::unloadPlugins();

    RSettings::uninit();
    RFontList::uninit();
    RPatternListMetric::uninit();
    RPatternListImperial::uninit();
    RSingleton::cleanUp();
    RMath::uninit();

    RDocumentInterface::deleteClipboard();

    //RDebug::printCounters();

    return ret;
}

 

 类似资料: