Telegram 客户端源码瞎读笔记-1

客户端界面主要采用部分QT来写吧,又自己封装糅合了N层东西。打算从头到尾一步一步看看吧程序入口 main.cpp的main函数。

int main(int argc, char *argv[])

通过platform_launcher.h 里的来控制平台相关的东西

#ifdef Q_OS_MAC #include "platform/mac/launcher_mac.h" #elif defined Q_OS_UNIX // Q_OS_MAC #include "platform/linux/launcher_linux.h" #elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX #include "platform/win/launcher_win.h" #endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WINRT || Q_OS_WIN

我就只看windows的了,Mac,linux就不考虑了,没那么多精力

只需要查看launcher_win.cpp的内容就可以了。

auto parseMap = std::map<QByteArray, KeyFormat> { { "-debug", KeyFormat::NoValues }, { "-freetype" , KeyFormat::NoValues }, { "-many" , KeyFormat::NoValues }, { "-key", KeyFormat::OneValue }, { "-autostart", KeyFormat::NoValues }, { "-fixprevious", KeyFormat::NoValues }, { "-cleanup", KeyFormat::NoValues }, { "-noupdate" , KeyFormat::NoValues }, { "-tosettings" , KeyFormat::NoValues }, { "-startintray", KeyFormat::NoValues }, { "-sendpath" , KeyFormat::AllLeftValues }, { "-workdir", KeyFormat::OneValue }, { "--", KeyFormat::OneValue }, { "-scale", KeyFormat::OneValue }, };

之后会调用基类 的函数

int Launcher::executeApplication() int Sandbox::start()

在Sandbox里会用socket连一下监听的一个端口,假如连不上,就表示当前没有tg在运行,然后接着启动程序,并监听XX接口,如果已经存在怎么判断是否允许多开。

connect( &_localSocket, base::QLocalSocket_error, [=](QLocalSocket::LocalSocketError error) { socketError(error); });

之后执行到void Sandbox::singleInstanceChecked()里的launchApplication()==》void Application::run()

这里才正式启动了界面。

其中遇见了几段比较有意思的,或者说平时比较少见的代码,记录一下

1.v::match

const auto result = CrashReports::Start(); v::match(result, [&](CrashReports::Status status) { if (status == CrashReports::CantOpen) { new NotStartedWindow(); } else { launchApplication(); } }, [&](const QByteArray &crashdump) { // If crash dump is empty with that status it means that we // didnt close the application properly. Just ignore for now. if (crashdump.isEmpty()) { if (CrashReports::Restart() == CrashReports::CantOpen) { new NotStartedWindow(); } else { launchApplication(); } return; } _lastCrashDump = crashdump; auto window = new LastCrashedWindow( _launcher, _lastCrashDump, [=] { launchApplication(); }); window->proxyChanges( ) | rpl::start_with_next([=](MTP::ProxyData &&proxy) { _sandboxProxy = std::move(proxy); refreshGlobalProxy(); }, window->lifetime()); });

这里的v::match的主要目的是依据result 的类型来选择匹配的函数,在这里返回的是const QByteArray,所以选择的是第二个函数,主要是利用模板的特性吧,具体可以看下源码

2._window = std::make_unique<Window::Controller>();

_window最终指的的是mainwindow整个界面,和mainwindow里的body是不一样的,body()指的是客户区