main.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. #include "ccnotepad.h"
  2. #include "jsondeploy.h"
  3. #include "styleset.h"
  4. #include <QtWidgets/QApplication>
  5. #include <QTextCodec>
  6. #include <QMessageBox>
  7. #include <QSharedMemory>
  8. #include <QFile>
  9. #include <QStatusBar>
  10. #include <qobject.h>
  11. #include <QThread>
  12. #include <QDir>
  13. #ifdef Q_OS_UNIX
  14. #include <QStyleFactory>
  15. #include <signal.h>
  16. #include <unistd.h>
  17. #include <QDebug>
  18. #include <QWidget>
  19. #endif
  20. #ifdef Q_OS_WIN
  21. #pragma comment(lib, "user32.lib")
  22. #include <qt_windows.h>
  23. const ULONG_PTR CUSTOM_TYPE = 10000;
  24. const ULONG_PTR OPEN_NOTEPAD_TYPE = 10001;
  25. bool s_isAdminAuth = false;
  26. #endif
  27. const QString c_strTitle = "notepad--";
  28. #ifdef Q_OS_UNIX
  29. #if defined(Q_OS_MAC)
  30. QSharedMemory shared("CCNotebook116");;//mac下面后面带一个版本号,避免新的打不开
  31. #else
  32. QSharedMemory shared("CCNotebook");
  33. #endif
  34. QSharedMemory nppShared("notepad--");
  35. static void sig_usr(int signo)
  36. {
  37. if(signo == SIGUSR1)
  38. {
  39. qlonglong winId;
  40. shared.lock();
  41. memcpy(&winId,shared.data(),sizeof(qlonglong));
  42. shared.unlock();
  43. QWidget *pMain = QWidget::find((WId)winId);
  44. CCNotePad* pNotePad = dynamic_cast<CCNotePad*>(pMain);
  45. if(pNotePad != nullptr)
  46. {
  47. QString filePath((char*)nppShared.data()+4);
  48. if(!filePath.isEmpty())
  49. {
  50. pNotePad->openFile(filePath);
  51. }
  52. pNotePad->activateWindow();
  53. pNotePad->showNormal();
  54. qDebug() << "sig_usr" << filePath;
  55. }
  56. }
  57. }
  58. #endif
  59. #ifdef Q_OS_MAC
  60. static void openfile(QString filePath)
  61. {
  62. qlonglong winId;
  63. shared.lock();
  64. memcpy(&winId,shared.data(),sizeof(qlonglong));
  65. shared.unlock();
  66. QWidget *pMain = QWidget::find((WId)winId);
  67. CCNotePad* pNotePad = dynamic_cast<CCNotePad*>(pMain);
  68. if(pNotePad != nullptr)
  69. {
  70. if(!filePath.isEmpty())
  71. {
  72. pNotePad->openFile(filePath);
  73. }
  74. pNotePad->activateWindow();
  75. pNotePad->showNormal();
  76. }
  77. }
  78. class MyApplication : public QApplication
  79. {
  80. public:
  81. MyApplication(int &argc, char **argv)
  82. : QApplication(argc, argv)
  83. {
  84. }
  85. bool event(QEvent *event)
  86. {
  87. if (event->type() == QEvent::FileOpen) {
  88. QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event);
  89. qDebug() << "Open file" << openEvent->file();
  90. s_openfile = openEvent->file();
  91. openfile(s_openfile);
  92. }
  93. return QApplication::event(event);
  94. }
  95. QString s_openfile;
  96. };
  97. #endif
  98. int main(int argc, char *argv[])
  99. {
  100. #ifdef Q_OS_MAC
  101. MyApplication a(argc, argv);
  102. #else
  103. QApplication a(argc, argv);
  104. #endif
  105. QDir::setCurrent(QCoreApplication::applicationDirPath());
  106. #if defined(Q_OS_UNIX)
  107. QApplication::setStyle(QStyleFactory::create("fusion"));
  108. #endif
  109. a.setApplicationDisplayName(c_strTitle);
  110. a.setApplicationName(c_strTitle);
  111. QStringList arguments = QCoreApplication::arguments();
  112. #ifdef Q_OS_WIN
  113. QSharedMemory shared("ccnotepad");
  114. if (arguments.size() > 2)
  115. {
  116. //如果是多开请求,这种是从管理员权限申请后重开过来的
  117. if (arguments[1] == QString("-muti"))
  118. {
  119. s_isAdminAuth = true;
  120. QString title = QString(u8"%1 管理员").arg(c_strTitle);
  121. a.setApplicationDisplayName(title);
  122. //删除-muti这个参数
  123. arguments.removeAt(1);
  124. //管理员不占用共享标志。这样的目的是,当管理员窗口存在时
  125. //打开原来的文件,原来的文件可以占用共享标志,作为主窗口打开。
  126. //管理员窗口永远不做主窗口打开
  127. goto authAdmin;
  128. }
  129. }
  130. #endif
  131. //attach成功表示已经存在该内存了,表示当前存在实例
  132. if (shared.attach())//共享内存被占用则直接返回
  133. {
  134. //发现在文件中如果存在空格时,参数不止1个,所以不能单纯用2个参数表示
  135. if (arguments.size() > 1)
  136. {
  137. #if defined(Q_OS_WIN)
  138. qlonglong hwndId;
  139. shared.lock();
  140. memcpy(&hwndId, shared.data(), sizeof(qlonglong));
  141. shared.unlock();
  142. HWND hwnd = (HWND)hwndId;
  143. if (::IsWindow(hwnd))
  144. {
  145. //去掉第一个参数,后续的参数拼接起来。其实参数中间有空格还是需要使用""引用起来,避免空格参数分隔为多个
  146. arguments.takeFirst();
  147. QString filename = arguments.join("");
  148. QByteArray data = filename.toUtf8();
  149. COPYDATASTRUCT copydata;
  150. copydata.dwData = CUSTOM_TYPE; //自定义类型
  151. copydata.lpData = data.data(); //数据大小
  152. copydata.cbData = data.size(); // 指向数据的指针
  153. ::SendMessage(hwnd, WM_COPYDATA, reinterpret_cast<WPARAM>(nullptr), reinterpret_cast<LPARAM>(&copydata));
  154. }
  155. else
  156. {
  157. //失败了,此时说明前一个窗口极可能状态错误了。如果不处理,则再也打不开程序了
  158. goto drop_old;
  159. }
  160. #elif defined (Q_OS_MAC)
  161. {
  162. //mac下面不需要,有他自身的机制保证
  163. }
  164. #else
  165. pid_t pid;
  166. arguments.takeFirst();
  167. QString filename = arguments.join("");
  168. QByteArray data = filename.toUtf8();
  169. nppShared.attach();
  170. nppShared.lock();
  171. memcpy(&pid, nppShared.data(), sizeof(pid_t));
  172. memset((char*)nppShared.data()+sizeof(pid_t),0, 1024-sizeof(pid_t));
  173. memcpy((char*)nppShared.data()+sizeof(pid_t),data.data(),data.size());
  174. nppShared.unlock();
  175. kill(pid,SIGUSR1);
  176. #endif
  177. }
  178. else if (arguments.size() == 1)
  179. {
  180. #if defined(Q_OS_WIN)
  181. //把窗口设置到最前
  182. qlonglong hwndId;
  183. shared.lock();
  184. memcpy(&hwndId, shared.data(), sizeof(qlonglong));
  185. shared.unlock();
  186. HWND hwnd = (HWND)hwndId;
  187. if (::IsWindow(hwnd))
  188. {
  189. QString filename("open");
  190. QByteArray data = filename.toUtf8();
  191. COPYDATASTRUCT copydata;
  192. copydata.dwData = OPEN_NOTEPAD_TYPE; //自定义类型
  193. copydata.lpData = data.data(); //数据大小
  194. copydata.cbData = data.size(); // 指向数据的指针
  195. ::SendMessage(hwnd, WM_COPYDATA, reinterpret_cast<WPARAM>(nullptr), reinterpret_cast<LPARAM>(&copydata));
  196. }
  197. else
  198. {
  199. //失败了,此时说明前一个窗口极可能状态错误了。如果不处理,则再也打不开程序了
  200. //继续新开一个窗口,放弃之前的旧内容
  201. goto drop_old;
  202. }
  203. #elif defined (Q_OS_MAC)
  204. {
  205. //mac下面不需要,有他自身的机制保证
  206. }
  207. #else
  208. pid_t pid;
  209. nppShared.attach();
  210. nppShared.lock();
  211. memcpy(&pid, nppShared.data(), sizeof(pid_t));
  212. memset((char*)nppShared.data()+sizeof(pid_t),0, 1024-sizeof(pid_t));
  213. nppShared.unlock();
  214. qDebug()<<"empty file send";
  215. kill(pid,SIGUSR1);
  216. #endif
  217. }
  218. return 0;
  219. }
  220. #if defined(Q_OS_WIN)
  221. shared.create(32);
  222. #elif defined (Q_OS_MAC)
  223. {
  224. //mac下面不需要,有他自身的机制保证。当程序已经在线时,再打开程序,系统会自动调用已经存在的程序出现
  225. //不需要使用类似linux下面的机制。
  226. shared.create(32);
  227. nppShared.create(32);
  228. }
  229. #else
  230. shared.create(32);
  231. nppShared.create(2048);
  232. if(signal(SIGUSR1,sig_usr) == SIG_ERR)
  233. {
  234. qDebug()<<"linux create sign failed";
  235. }
  236. #endif
  237. #if defined(Q_OS_WIN)
  238. authAdmin:
  239. drop_old:
  240. #endif
  241. //20221009发现有小概率出现窗口没有,但是进程还在的诡异问题,加个保护一下
  242. QApplication::setQuitOnLastWindowClosed(true);
  243. JsonDeploy::init();
  244. int id = JsonDeploy::getKeyValueFromNumSets(SKIN_KEY);
  245. StyleSet::setSkin(id);
  246. CCNotePad *pMainNotepad = new CCNotePad(true);
  247. pMainNotepad->setAttribute(Qt::WA_DeleteOnClose);
  248. pMainNotepad->setShareMem(&shared);
  249. pMainNotepad->show();
  250. pMainNotepad->syncCurSkinToMenu(id);
  251. #ifdef uos
  252. QFont font("Noto Sans CJK JP,9,-1,5,50,0,0,0,0,0,Regular", 9);
  253. QApplication::setFont(font);
  254. #endif
  255. #ifdef Q_OS_MAC
  256. //这里的字体大小,务必要和查找结果框的高度匹配,否则会结构字体拥挤
  257. QFont font("Courier New,11,-1,5,50,0,0,0,0,0,Regular", 11);
  258. QApplication::setFont(font);
  259. #endif
  260. #ifdef Q_OS_WIN
  261. //HWND hwnd = ::FindWindowA("Qt5QWindowIcon", "CCNotebook");
  262. //发现hwnd就是和effectiveWinId相等的,不需要查询了
  263. //管理员可以多开,暂时不把管理员的权限作为主窗口,因为其他用户没有权限右键菜单发送消息给管理员窗口去打开文件
  264. if (!s_isAdminAuth)
  265. {
  266. qlonglong winId = (qlonglong)pMainNotepad->effectiveWinId();
  267. shared.lock();
  268. memcpy(shared.data(), &winId, sizeof(qlonglong));
  269. shared.unlock();
  270. }
  271. #else
  272. qlonglong winId = (qlonglong)pMainNotepad->effectiveWinId();
  273. shared.lock();
  274. memcpy(shared.data(), &winId, sizeof(qlonglong));
  275. shared.unlock();
  276. nppShared.attach();
  277. //get proceess id to share memory
  278. pid_t pid = getpid();
  279. nppShared.lock();
  280. memcpy(nppShared.data(), &pid, sizeof(pid_t));
  281. nppShared.unlock();
  282. #endif // Q_OS_WIN
  283. //else
  284. //{
  285. // pMainNotepad->initTabNewOne();
  286. //}
  287. //恢复上次关闭时的文件
  288. #ifdef Q_OS_WIN
  289. if (!s_isAdminAuth)
  290. {
  291. if (0 == pMainNotepad->restoreLastFiles())
  292. {
  293. pMainNotepad->initTabNewOne();
  294. }
  295. }
  296. #else
  297. if (0 == pMainNotepad->restoreLastFiles())
  298. {
  299. pMainNotepad->initTabNewOne();
  300. }
  301. #endif
  302. if (arguments.size() == 2)
  303. {
  304. pMainNotepad->openFile(arguments[1]);
  305. pMainNotepad->showNormal();
  306. }
  307. #ifdef Q_OS_WIN
  308. pMainNotepad->checkAppFont();
  309. #endif
  310. a.exec();
  311. JsonDeploy::close();
  312. return 0;
  313. }