PageRenderTime 61ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/CMain.cpp

https://bitbucket.org/skynowa/start
C++ | 2264 lines | 1636 code | 373 blank | 255 comment | 105 complexity | f3ce89ba9bd20af46d091e51c19c0b1a MD5 | raw file
  1. /**
  2. * \file CMain.h
  3. * \brief main window
  4. */
  5. #include "CMain.h"
  6. #include "Forms/CLinkProperties.h"
  7. //------------------------------------------------------------------------------
  8. CMain::CMain(
  9. QWidget *a_parent
  10. ) :
  11. QDialog (a_parent),
  12. #if defined(Q_OS_X11)
  13. _m_hlHAl (a_parent),
  14. #endif
  15. _m_tabLinks (NULL),
  16. _m_dbDatabase (),
  17. _m_smapToolButtons (),
  18. _m_smapLinks (),
  19. _m_tmSystemUsage (),
  20. _m_tmTemperatureUsage(),
  21. _m_tmCurrentDateTime (),
  22. _m_nmNetworkManager (this),
  23. _m_bIsAllowWrap (true),
  24. _m_bIsLinkSwap (false),
  25. _m_btnLinkFrom (NULL),
  26. _m_mnuDirs (),
  27. _m_ptMousePos ()
  28. {
  29. // backup DB
  30. {
  31. CxBackup backup(CxBackup::bpDaily);
  32. try {
  33. std::tstring_t sBackupFilePath;
  34. backup.fileExec(CxPath::exe() + xT(DB_FILE_EXT),
  35. CxPath::exeDir() + CxConst::slash() + xT(BACKUP_DIR_NAME),
  36. &sBackupFilePath);
  37. }
  38. catch (const CxException &e) {
  39. cQString csMsg = QString("CxBackup: ") + qS2QS(e.what());
  40. QMessageBox::warning(this, qApp->applicationName(), csMsg, QMessageBox::Ok);
  41. }
  42. }
  43. _construct();
  44. _settingsLoad();
  45. }
  46. //------------------------------------------------------------------------------
  47. /*******************************************************************************
  48. * CMain
  49. *
  50. *******************************************************************************/
  51. //------------------------------------------------------------------------------
  52. void
  53. CMain::_construct() {
  54. ui.setupUi(this);
  55. //--------------------------------------------------
  56. // settings DB
  57. {
  58. bool bRv = QSqlDatabase::isDriverAvailable("QSQLITE");
  59. qCHECK_DO(false == bRv, qMSG(QSqlDatabase().lastError().text()); return;);
  60. _m_dbDatabase = QSqlDatabase::addDatabase("QSQLITE");
  61. _m_dbDatabase.setDatabaseName(DB_FILE_PATH);
  62. bRv = _m_dbDatabase.open();
  63. qCHECK_REF(bRv, _m_dbDatabase);
  64. {
  65. QSqlQuery qryTable(_m_dbDatabase);
  66. cQString csSql = \
  67. "CREATE TABLE IF NOT EXISTS t_tabs"
  68. "( "
  69. " f_id INTEGER PRIMARY KEY AUTOINCREMENT "
  70. " NOT NULL "
  71. " UNIQUE, "
  72. " f_name VARCHAR(64) NOT NULL "
  73. " UNIQUE "
  74. ")";
  75. bRv = qryTable.exec(csSql);
  76. qCHECK_REF(bRv, qryTable);
  77. }
  78. {
  79. QSqlQuery qryTable(_m_dbDatabase);
  80. cQString csSql = \
  81. "CREATE TABLE IF NOT EXISTS t_main"
  82. "( "
  83. " f_id INTEGER PRIMARY KEY AUTOINCREMENT "
  84. " NOT NULL "
  85. " UNIQUE, "
  86. " f_tab_index INTEGER NOT NULL "
  87. " REFERENCES t_tabs (f_id) "
  88. " ON DELETE RESTRICT "
  89. " ON UPDATE CASCADE, "
  90. " f_link_index INTEGER NOT NULL, "
  91. " f_text VARCHAR(64), "
  92. " f_file_path VARCHAR(255), "
  93. " f_file_params VARCHAR(64) "
  94. ")";
  95. bRv = qryTable.exec(csSql);
  96. qCHECK_REF(bRv, qryTable);
  97. }
  98. }
  99. //--------------------------------------------------
  100. // CMain
  101. {
  102. setWindowTitle(APP_NAME);
  103. // remove window title bar, taskbar
  104. {
  105. Qt::WindowFlags wfFlags = windowFlags();
  106. wfFlags |= Qt::ToolTip;
  107. setWindowFlags(wfFlags);
  108. }
  109. // wrap window
  110. {
  111. cint ciTitleHeight = ui.frTitle->geometry().height();
  112. cint ciTargetHeight = ciTitleHeight;
  113. setFixedHeight(ciTargetHeight);
  114. }
  115. CUtils::widgetAlwaysOnTop(this, true);
  116. }
  117. //--------------------------------------------------
  118. // header
  119. {
  120. // tbtnMenuDirs
  121. _menuDirs_Create(&_m_mnuDirs, ui.tbtnMenuDirs);
  122. ui.tbtnMenuDirs->setPopupMode(QToolButton::InstantPopup);
  123. ui.tbtnMenuDirs->setMenu(&_m_mnuDirs);
  124. ui.tbtnMenuDirs->setIcon(QProxyStyle().standardIcon(QStyle::SP_DirHomeIcon));
  125. #if 0
  126. // tbtnMenuRun
  127. ui.tbtnMenuRun->setPopupMode(QToolButton::InstantPopup);
  128. ui.tbtnMenuRun->setIcon(QProxyStyle().standardIcon(QStyle::SP_CommandLink));
  129. connect(ui.tbtnMenuRun, SIGNAL(pressed()),
  130. this, SLOT (tbtnMenuRun_OnPressed);
  131. #endif
  132. // btnClose
  133. ui.btnClose->setText("");
  134. ui.btnClose->setIcon(QProxyStyle().standardIcon(QStyle::SP_TitleBarCloseButton));
  135. // lblTemperatureUsage
  136. ui.lblTemperatureUsage->setText("<b>T:</b> - ");
  137. // prgCpuUsage, prgMemoryUsage
  138. ui.prgCpuUsage->setFormat("");
  139. ui.prgCpuUsage->setOrientation(Qt::Vertical);
  140. ui.prgCpuUsage->setMaximum(0);
  141. ui.prgCpuUsage->setMaximum(100);
  142. ui.prgCpuUsage->setValue(0);
  143. ui.prgMemoryUsage->setFormat("");
  144. ui.prgMemoryUsage->setOrientation(Qt::Vertical);
  145. ui.prgMemoryUsage->setMaximum(0);
  146. ui.prgMemoryUsage->setMaximum(100);
  147. ui.prgMemoryUsage->setValue(0);
  148. // update usage
  149. systemUsage_OnTimeout();
  150. }
  151. /***************************************************************************
  152. * setup slots
  153. *
  154. ***************************************************************************/
  155. #if defined(Q_OS_X11)
  156. //--------------------------------------------------
  157. // insert/remove device events
  158. {
  159. connect(&_m_hlHAl, &CMain::signal_OnAdded,
  160. this, &CMain::slot_Hal_OnAdded);
  161. connect(&_m_hlHAl, &CMain::signal_OnRemoved,
  162. this, &CMain::slot_Hal_OnRemoved);
  163. }
  164. #endif
  165. //--------------------------------------------------
  166. // signal mappers
  167. {
  168. connect(&_m_smapToolButtons, SIGNAL(mapped(QWidget *)),
  169. this, SLOT (btnVolume_OnClicked(QWidget *)));
  170. connect(&_m_smapLinks, SIGNAL(mapped(QWidget *)),
  171. this, SLOT (btnLink_OnClicked(QWidget *)));
  172. }
  173. //--------------------------------------------------
  174. // "My computer" button
  175. {
  176. ui.tbtnMyComputer->setGeometry( 0 * BUTTON_WIDTH, BUTTON_MARGIN, BUTTON_WIDTH, BUTTON_HEIGHT);
  177. ui.tbtnMyComputer->setAutoRaise(true);
  178. ui.tbtnMyComputer->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  179. _m_smapToolButtons.setMapping(ui.tbtnMyComputer, ui.tbtnMyComputer);
  180. connect(ui.tbtnMyComputer, &QToolButton::clicked,
  181. this, &CMain::mnuDirs_OnMyComputer);
  182. // ui.tbtnMyComputer->setMenu();
  183. }
  184. //--------------------------------------------------
  185. // volume buttons
  186. {
  187. // fill container
  188. _m_vtbVolumes.push_back(ui.tbtnVolume1);
  189. _m_vtbVolumes.push_back(ui.tbtnVolume2);
  190. _m_vtbVolumes.push_back(ui.tbtnVolume3);
  191. _m_vtbVolumes.push_back(ui.tbtnVolume4);
  192. _m_vtbVolumes.push_back(ui.tbtnVolume5);
  193. _m_vtbVolumes.push_back(ui.tbtnVolume6);
  194. _m_vtbVolumes.push_back(ui.tbtnVolume7);
  195. _m_vtbVolumes.push_back(ui.tbtnVolume8);
  196. // set options
  197. for (int i = 0; i < _m_vtbVolumes.size(); ++ i) {
  198. // start from 2-nd toolbutton
  199. _m_vtbVolumes.at(i)->setGeometry((i + 1) * BUTTON_WIDTH, BUTTON_MARGIN, BUTTON_WIDTH, BUTTON_HEIGHT);
  200. _m_vtbVolumes.at(i)->setAutoRaise(true);
  201. _m_vtbVolumes.at(i)->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  202. _m_smapToolButtons.setMapping(_m_vtbVolumes.at(i), _m_vtbVolumes.at(i));
  203. connect(_m_vtbVolumes.at(i), SIGNAL(clicked()),
  204. &_m_smapToolButtons, SLOT (map()));
  205. }
  206. _volumes_Rebuild(&_m_vtbVolumes);
  207. }
  208. //--------------------------------------------------
  209. // CMain
  210. {
  211. connect(this, &CMain::signal_title_LClicked,
  212. this, &CMain::title_OnLClicked);
  213. connect(this, &CMain::signal_title_RClicked,
  214. this, &CMain::title_OnRClicked);
  215. ui.frTitle->installEventFilter(this);
  216. connect(&_m_tmSystemUsage, &QTimer::timeout,
  217. this, &CMain::systemUsage_OnTimeout);
  218. // set timeout only for the 1-st launch
  219. _m_tmSystemUsage.start(SYTEM_USAGE_STARTUP_TIMEOUT);
  220. connect(&_m_tmTemperatureUsage, &QTimer::timeout,
  221. this, &CMain::weatherTemp_OnTimeout);
  222. // set timeout only for the 1-st launch
  223. _m_tmTemperatureUsage.start(SYTEM_USAGE_STARTUP_TIMEOUT);
  224. connect(&_m_tmCurrentDateTime, &QTimer::timeout,
  225. this, &CMain::currentDate_OnTimeout);
  226. _m_tmCurrentDateTime.start(CURRENT_DATETIME_TIMEOUT);
  227. connect(&_m_nmNetworkManager, &QNetworkAccessManager::finished,
  228. this, &CMain::networkReply_OnFinished);
  229. connect(ui.btnClose, &QToolButton::clicked,
  230. this, &CMain::btnClose_OnClicked);
  231. }
  232. //--------------------------------------------------
  233. // _m_tabLinks
  234. {
  235. _m_tabLinks = new CTabWidgetEx(this);
  236. xTEST_PTR(_m_tabLinks);
  237. _m_tabLinks->setParent(this);
  238. _m_tabLinks->setMovable(true);
  239. _m_tabLinks->setGeometry(0, TITLEBAR_HEIGHT * 2, TABLINKS_WIDTH, TABLINKS_HEIGHT);
  240. _m_tabLinks->setContextMenuPolicy(Qt::CustomContextMenu);
  241. _m_tabLinks->setCurrentIndex(0); // 0 - first tab
  242. _m_tabLinks->setVisible(true);
  243. connect(_m_tabLinks->tabBarEx(), &QTabBar::tabMoved,
  244. this, &CMain::tabLinks_OnMoved);
  245. connect(_m_tabLinks, SIGNAL(customContextMenuRequested(const QPoint &)),
  246. SLOT (mnuLinks_OnShow(const QPoint &)));
  247. }
  248. //--------------------------------------------------
  249. // create tab pages
  250. {
  251. // from DB
  252. QSqlQuery qryTabs(_m_dbDatabase);
  253. cQString csSql = \
  254. "SELECT f_name FROM t_tabs";
  255. bool bRv = qryTabs.exec(csSql);
  256. qCHECK_REF(bRv, qryTabs);
  257. // create
  258. for ( ; true == qryTabs.next(); ) {
  259. cQString csTabName = qryTabs.value(0).toString(); // 0 - f_name
  260. _tabPageShow(csTabName);
  261. }
  262. }
  263. //--------------------------------------------------
  264. // statusbar
  265. {
  266. // font
  267. {
  268. QFont fntFont( ui.lblDayOfWeek->font() );
  269. fntFont.setPointSize( ui.lblDayOfWeek->font().pointSize() );
  270. fntFont.setBold(false);
  271. ui.lblDayOfWeek->setFont(fntFont);
  272. }
  273. // ui.lblDayOfWeek->setAlignment(Qt::AlignCenter);
  274. currentDate_OnTimeout();
  275. }
  276. }
  277. //------------------------------------------------------------------------------
  278. void
  279. CMain::_destruct() {
  280. _settingsSave();
  281. }
  282. //------------------------------------------------------------------------------
  283. void
  284. CMain::title_OnLClicked() {
  285. int iTitleHeight = 0;
  286. int iTargetHeight = 0;
  287. if (TITLEBAR_HEIGHT == height()) {
  288. // unwrap main window
  289. iTitleHeight = ui.frTitle->geometry().height();
  290. iTargetHeight = iTitleHeight + TITLEBAR_HEIGHT + _m_tabLinks->height();
  291. } else {
  292. // wrap main window
  293. qCHECK_DO(false == _m_bIsAllowWrap, return);
  294. iTitleHeight = ui.frTitle->geometry().height();
  295. iTargetHeight = iTitleHeight;
  296. }
  297. setFixedWidth(width());
  298. setFixedHeight(iTargetHeight);
  299. }
  300. //------------------------------------------------------------------------------
  301. void
  302. CMain::title_OnRClicked() {
  303. static bool s_bFlagIsMinimize = false;
  304. s_bFlagIsMinimize = !s_bFlagIsMinimize;
  305. // TODO: CUtils::desktopWindowsMinimize(s_bFlagIsMinimize);
  306. }
  307. //------------------------------------------------------------------------------
  308. void
  309. CMain::tbtnMenuRun_OnPressed() {
  310. // wrap window
  311. {
  312. cint iTitleHeight = ui.frTitle->geometry().height();
  313. cint iTargetHeight = iTitleHeight;
  314. setFixedHeight(iTargetHeight);
  315. }
  316. QClipboard *pcbClipboard = QApplication::clipboard();
  317. xTEST_PTR(pcbClipboard);
  318. cQString csProgram = pcbClipboard->text().trimmed();
  319. cQString cslArgs; // TODO: cslArgs
  320. qCHECK_DO(true == csProgram.isEmpty(), return);
  321. QString sDir = QString("file:///%1")
  322. .arg(csProgram);
  323. bool bRv = QDesktopServices::openUrl( QUrl(sDir) );
  324. xTEST_EQ(true, bRv);
  325. }
  326. //------------------------------------------------------------------------------
  327. /*******************************************************************************
  328. * protected
  329. *
  330. *******************************************************************************/
  331. //------------------------------------------------------------------------------
  332. /*virtual*/
  333. bool
  334. CMain::eventFilter(
  335. QObject *a_object,
  336. QEvent *a_event
  337. )
  338. {
  339. // title clicks
  340. if (ui.frTitle == a_object) {
  341. if (QEvent::MouseButtonPress == a_event->type()) {
  342. QMouseEvent *mouseEvent = static_cast<QMouseEvent *>( a_event );
  343. if (Qt::LeftButton == mouseEvent->button()) {
  344. emit signal_title_LClicked();
  345. }
  346. else if (Qt::RightButton == mouseEvent->button()) {
  347. emit signal_title_RClicked();
  348. }
  349. else {
  350. xNA;
  351. }
  352. }
  353. }
  354. return false;
  355. }
  356. //------------------------------------------------------------------------------
  357. /*virtual*/
  358. void
  359. CMain::focusInEvent(
  360. QFocusEvent *a_event
  361. )
  362. {
  363. if (true == a_event->gotFocus()) {
  364. _volumes_Rebuild(&_m_vtbVolumes);
  365. }
  366. QWidget::focusInEvent(a_event);
  367. }
  368. //------------------------------------------------------------------------------
  369. /*virtual*/
  370. void
  371. CMain::focusOutEvent(
  372. QFocusEvent *a_event
  373. )
  374. {
  375. if (true == a_event->lostFocus()) {
  376. if (TITLEBAR_HEIGHT < height()) {
  377. title_OnLClicked();
  378. }
  379. }
  380. QWidget::focusOutEvent(a_event);
  381. }
  382. //------------------------------------------------------------------------------
  383. /* virtual */
  384. void
  385. CMain::closeEvent(
  386. QCloseEvent *a_event
  387. )
  388. {
  389. _destruct();
  390. a_event->accept();
  391. }
  392. //------------------------------------------------------------------------------
  393. /*******************************************************************************
  394. * header - insert / remove device events
  395. *
  396. *******************************************************************************/
  397. //------------------------------------------------------------------------------
  398. #if defined(Q_OS_WIN)
  399. /* virtual */
  400. bool
  401. CMain::nativeEvent(
  402. cQByteArray &a_eventType,
  403. void *a_message,
  404. long *a_result
  405. )
  406. {
  407. /*
  408. * Platform Event Type Identifier Message Type Result Type
  409. * Windows "windows_generic_MSG" MSG * LRESULT
  410. */
  411. MSG *pmsgMsg = static_cast<MSG *>(a_message);
  412. Q_UNUSED(a_result);
  413. xCHECK_RET(NULL == pmsgMsg, false);
  414. // inserting volume
  415. if (WM_DEVICECHANGE == pmsgMsg->message &&
  416. DBT_DEVICEARRIVAL == pmsgMsg->wParam
  417. )
  418. {
  419. _volumes_Rebuild(&_m_vtbVolumes);
  420. return true;
  421. }
  422. // removing volume
  423. if (WM_DEVICECHANGE == pmsgMsg->message &&
  424. DBT_DEVICEREMOVECOMPLETE == pmsgMsg->wParam
  425. )
  426. {
  427. _volumes_Rebuild(&_m_vtbVolumes);
  428. return true;
  429. }
  430. return QWidget::nativeEvent(a_eventType, a_message, a_result);
  431. }
  432. #elif defined(Q_OS_X11)
  433. //------------------------------------------------------------------------------
  434. // HAL
  435. void
  436. CMain::slot_Hal_OnAdded(cQString &dev) {
  437. qDebug() << __FUNCTION__ << dev;
  438. _volumes_Rebuild(&_m_vtbVolumes);
  439. }
  440. //------------------------------------------------------------------------------
  441. void
  442. CMain::slot_Hal_OnRemoved(cQString &dev) {
  443. qDebug() << __FUNCTION__ << dev;
  444. _volumes_Rebuild(&_m_vtbVolumes);
  445. }
  446. //------------------------------------------------------------------------------
  447. #endif // Q_OS_X11
  448. /*******************************************************************************
  449. * header - GUI
  450. *
  451. *******************************************************************************/
  452. //------------------------------------------------------------------------------
  453. void
  454. CMain::systemUsage_OnTimeout() {
  455. CxSystemInfo info;
  456. const ulong_t culCpuUsage = info.cpuUsage();
  457. const ulong_t culRamUsage = info.ramUsage();
  458. cQString csCpuUsage = QString("<b>CPU:</b> %1%").arg(culCpuUsage);
  459. cQString csMemoryUsage = QString("<b>RAM:</b> %1%").arg(culRamUsage);
  460. // prgCpuUsage
  461. ui.prgCpuUsage->setValue(culCpuUsage);
  462. ui.prgCpuUsage->setToolTip(csCpuUsage);
  463. // prgMemoryUsage
  464. ui.prgMemoryUsage->setValue(culRamUsage);
  465. ui.prgMemoryUsage->setToolTip(csMemoryUsage);
  466. }
  467. //------------------------------------------------------------------------------
  468. void
  469. CMain::weatherTemp_OnTimeout() {
  470. _m_tmTemperatureUsage.setInterval(WEATHER_TEMPR_CHECK_TIMEOUT);
  471. #if 0
  472. /**
  473. * Google API
  474. *
  475. * FAQ:
  476. * HTTP GET: http://www.google.com/ig/api?weather=kiev&hl=en
  477. */
  478. QUrl urUrl("http://www.google.com/ig/api");
  479. urUrl.addEncodedQueryItem("weather", QUrl::toPercentEncoding(WEATHER_TEMPR_CITY));
  480. urUrl.addEncodedQueryItem("hl", "en");
  481. #endif
  482. /**
  483. * Yahoo API
  484. *
  485. * FAQ: http://developer.yahoo.com/weather/
  486. * HTTP GET: http://weather.yahooapis.com/forecastrss?w=924938&u=c
  487. */
  488. QUrl urUrl("http://weather.yahooapis.com/forecastrss?w=924938&u=c");
  489. urUrl.toEncoded();
  490. QNetworkRequest nrRequest;
  491. nrRequest.setUrl(urUrl);
  492. #if 1
  493. _m_nmNetworkManager.get(nrRequest);
  494. #endif
  495. }
  496. //------------------------------------------------------------------------------
  497. void
  498. CMain::currentDate_OnTimeout() {
  499. cQString csDate = QDate().currentDate().toString("dd.MM.yyyy");
  500. cQString csDayOfWeek = QDate().currentDate().toString("ddd");
  501. cQString csTime = QTime().currentTime().toString("H:mm");
  502. cQString csDateTimeFormated = QString("<b>%1</b> <u>%2</u> %3")
  503. .arg(csTime)
  504. .arg(csDayOfWeek)
  505. .arg(csDate);
  506. ui.lblDayOfWeek->setText(csDateTimeFormated);
  507. }
  508. //------------------------------------------------------------------------------
  509. void
  510. CMain::networkReply_OnFinished(
  511. QNetworkReply *a_pnrReply
  512. )
  513. {
  514. QString sRv;
  515. cint ciStatus = a_pnrReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
  516. if (200 == ciStatus) {
  517. cQString csText = QString::fromUtf8(a_pnrReply->readAll());
  518. sRv = QString("<b>T:</b> %1").arg( _yahooReplyParse(csText) );
  519. } else {
  520. qDebug() << "ciStatus: " << ciStatus;
  521. sRv = QString("<b>T:</b> %1").arg("-");
  522. }
  523. ui.lblTemperatureUsage->setText(sRv);
  524. a_pnrReply->deleteLater();
  525. }
  526. //------------------------------------------------------------------------------
  527. QString
  528. CMain::_googleReplyParse(
  529. cQString &a_csXml
  530. )
  531. {
  532. QXmlStreamReader xml(a_csXml);
  533. while (!xml.atEnd()) {
  534. xml.readNext();
  535. qCHECK_DO(QXmlStreamReader::StartElement != xml.tokenType(), continue);
  536. // Parse current weather conditions
  537. if (xml.name() == "current_conditions") {
  538. while (!xml.atEnd()) {
  539. xml.readNext();
  540. if ("current_conditions" == xml.name()) {
  541. break;
  542. }
  543. if (QXmlStreamReader::StartElement == xml.tokenType()) {
  544. if ("temp_c" == xml.name()) {
  545. QString sTempr = xml.attributes().value("data").toString().trimmed();
  546. xCHECK_RET(true == sTempr.isEmpty(), "-");
  547. // add "+" prefix to temperature
  548. if ("-" == sTempr.at(0)) {
  549. xNA;
  550. } else {
  551. sTempr = "+" + sTempr;
  552. }
  553. return QString("%1%2%3")
  554. .arg(sTempr)
  555. .arg(QChar(176))
  556. .arg("C");
  557. }
  558. }
  559. }
  560. }
  561. }
  562. return "-";
  563. }
  564. //------------------------------------------------------------------------------
  565. QString
  566. CMain::_yahooReplyParse(
  567. cQString &a_csXml
  568. )
  569. {
  570. QXmlStreamReader xml(a_csXml);
  571. while (!xml.atEnd()) {
  572. xml.readNext();
  573. qCHECK_DO(QXmlStreamReader::StartElement != xml.tokenType(), continue);
  574. // parse:
  575. // <yweather:condition text="Light Rain Shower" code="11" temp="5"
  576. // date="Thu, 11 Oct 2012 9:58 am EEST" />
  577. if (xml.name() == "condition") {
  578. QString sTempr = xml.attributes().value("temp").toString().trimmed();
  579. qCHECK_RET(true == sTempr.isEmpty(), "-");
  580. // add "+" prefix to temperature
  581. if ("-" == sTempr.at(0)) {
  582. xNA;
  583. } else {
  584. sTempr = "+" + sTempr;
  585. }
  586. return QString("%1%2%3")
  587. .arg(sTempr)
  588. .arg(QChar(176))
  589. .arg("C");
  590. }
  591. }
  592. return "-";
  593. }
  594. //------------------------------------------------------------------------------
  595. void
  596. CMain::_settingsLoad() {
  597. QSize szSize;
  598. QPoint pnPosition;
  599. {
  600. QSettings stSettings(INI_FILE_PATH, QSettings::IniFormat, this);
  601. stSettings.beginGroup("main");
  602. szSize = stSettings.value("size", APP_SIZE).toSize();
  603. pnPosition = stSettings.value("position", QPoint(200, 200)).toPoint();
  604. stSettings.endGroup();
  605. }
  606. // apply settings
  607. {
  608. resize(szSize);
  609. move(pnPosition);
  610. }
  611. }
  612. //------------------------------------------------------------------------------
  613. void
  614. CMain::_settingsSave() {
  615. QSettings stSettings(INI_FILE_PATH, QSettings::IniFormat, this);
  616. stSettings.beginGroup("main");
  617. stSettings.setValue("position", pos());
  618. stSettings.setValue("size", size());
  619. stSettings.endGroup();
  620. }
  621. //------------------------------------------------------------------------------
  622. void
  623. CMain::btnClose_OnClicked() {
  624. close();
  625. }
  626. //------------------------------------------------------------------------------
  627. /*******************************************************************************
  628. * CLinkButton
  629. *
  630. *******************************************************************************/
  631. //------------------------------------------------------------------------------
  632. void
  633. CMain::_tabPageAddEmpty(
  634. cQString &a_tabName
  635. )
  636. {
  637. // to DB (t_tabs)
  638. {
  639. QSqlQuery qryInsert(_m_dbDatabase);
  640. cQString csSql = \
  641. "INSERT INTO t_tabs (f_name) VALUES (:p_tab_name)";
  642. bool bRv = qryInsert.prepare(csSql);
  643. qCHECK_REF(bRv, qryInsert)
  644. qryInsert.bindValue(":p_tab_name", a_tabName);
  645. bRv = qryInsert.exec();
  646. qCHECK_REF(bRv, qryInsert);
  647. }
  648. // DB (t_main)
  649. {
  650. cint _ciTabIndex = _m_tabLinks->count();
  651. for (int x = 0, index = 0; x < TAB_X; ++ x) {
  652. for (int y = 0; y < TAB_Y; ++ y, ++ index) {
  653. cint ciTabIndex = _ciTabIndex;
  654. cint ciLinkIndex = index;
  655. cQString csText;
  656. cQString csFilePath;
  657. cQString csFileParams;
  658. QSqlQuery qryInsert(_m_dbDatabase);
  659. cQString csSql = \
  660. "INSERT INTO "
  661. " t_main (f_tab_index, f_link_index, f_text, f_file_path, f_file_params) "
  662. "VALUES "
  663. " (:p_tab_index, :p_link_index, :p_text, :p_file_path, :p_file_params)";
  664. bool bRv = qryInsert.prepare(csSql);
  665. qCHECK_REF(bRv, qryInsert)
  666. qryInsert.bindValue(":p_tab_index", ciTabIndex);
  667. qryInsert.bindValue(":p_link_index", ciLinkIndex);
  668. qryInsert.bindValue(":p_text", csText);
  669. qryInsert.bindValue(":p_file_path", csFilePath);
  670. qryInsert.bindValue(":p_file_params", csFileParams);
  671. bRv = qryInsert.exec();
  672. qCHECK_REF(bRv, qryInsert);
  673. }
  674. }
  675. }
  676. }
  677. //------------------------------------------------------------------------------
  678. void
  679. CMain::_tabPageShow(
  680. cQString &a_tabName
  681. )
  682. {
  683. cint _ciTabIndex = _m_tabLinks->addTab(new QWidget(), a_tabName);
  684. // build current tab (4x10)
  685. for (int x = 0, index = 0; x < TAB_X; ++ x) {
  686. for (int y = 0; y < TAB_Y; ++ y, ++ index) {
  687. cint ciTabIndex = _ciTabIndex;
  688. cint ciLinkIndex = index;
  689. QString sText;
  690. QString sFilePath;
  691. QString sFileParams;
  692. // DB (get link data from DB)
  693. {
  694. QSqlQuery qryLinks(_m_dbDatabase);
  695. cQString csSql = \
  696. "SELECT f_text, f_file_path, f_file_params "
  697. " FROM t_main "
  698. "WHERE "
  699. " (f_tab_index=:p_tab_index AND f_link_index=:p_link_index)";
  700. bool bRv = qryLinks.prepare(csSql);
  701. qCHECK_REF(bRv, qryLinks)
  702. qryLinks.bindValue(":p_tab_index", ciTabIndex);
  703. qryLinks.bindValue(":p_link_index", ciLinkIndex);
  704. bRv = qryLinks.exec();
  705. qCHECK_REF(bRv, qryLinks);
  706. // assignment
  707. if (true == qryLinks.next()) {
  708. sText = qryLinks.value(0).toString(); /* 0 - f_text */
  709. sFilePath = qryLinks.value(1).toString(); /* 1 - f_file_path */
  710. sFileParams = qryLinks.value(2).toString(); /* 2 - f_file_params */
  711. } else {
  712. sText.clear();
  713. sFilePath.clear();
  714. sFileParams.clear();
  715. }
  716. }
  717. // Ui
  718. {
  719. // create link
  720. CLinkButton *pbtnLink = new CLinkButton;
  721. xTEST_PTR(pbtnLink);
  722. pbtnLink->setGeometry(x * SHORTCUT_WIDTH, y * SHORTCUT_HEIGHT, SHORTCUT_WIDTH, SHORTCUT_HEIGHT);
  723. _linkUpdate(pbtnLink, ciTabIndex, ciLinkIndex, sText, sFilePath, sFileParams);
  724. // context menu
  725. pbtnLink->setContextMenuPolicy(Qt::CustomContextMenu);
  726. connect(pbtnLink, SIGNAL(customContextMenuRequested(const QPoint &)),
  727. SLOT (mnuLink_OnShow(const QPoint &)));
  728. // clicked()
  729. _m_smapLinks.setMapping(pbtnLink, pbtnLink);
  730. connect(pbtnLink, SIGNAL(clicked()),
  731. &_m_smapLinks, SLOT(map()));
  732. }
  733. }
  734. }
  735. }
  736. //------------------------------------------------------------------------------
  737. void
  738. CMain::_linkUpdate(
  739. CLinkButton *a_pbtnLink,
  740. cint &a_tabIndex,
  741. cint &a_linkIndex,
  742. cQString &a_text,
  743. cQString &a_filePath,
  744. cQString &a_fileParams
  745. )
  746. {
  747. xTEST_PTR(a_pbtnLink);
  748. xTEST_LESS(- 1, a_tabIndex);
  749. xTEST_LESS(- 1, a_linkIndex);
  750. // a_filePath - n/a
  751. // a_fileParams - n/a
  752. a_pbtnLink->setParent( _m_tabLinks->widget(a_tabIndex) );
  753. a_pbtnLink->setAutoRaise(true);
  754. a_pbtnLink->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  755. a_pbtnLink->setVisible(true);
  756. a_pbtnLink->setTabIndex(a_tabIndex);
  757. a_pbtnLink->setLinkIndex(a_linkIndex);
  758. // icon
  759. {
  760. QIcon icoIcon;
  761. if (true == a_filePath.isEmpty()) {
  762. xNA;
  763. } else {
  764. QFileInfo fiInfo(a_filePath);
  765. icoIcon = QFileIconProvider().icon(fiInfo);
  766. }
  767. a_pbtnLink->setIconSize(BUTTON_ICON_SIZE);
  768. a_pbtnLink->setIcon(icoIcon);
  769. }
  770. a_pbtnLink->setText(a_text);
  771. a_pbtnLink->setToolTip(a_filePath);
  772. a_pbtnLink->setFilePath(a_filePath);
  773. a_pbtnLink->setFileParams(a_fileParams);
  774. }
  775. //------------------------------------------------------------------------------
  776. /*******************************************************************************
  777. * _m_vtbVolumes
  778. *
  779. *******************************************************************************/
  780. //------------------------------------------------------------------------------
  781. void
  782. CMain::btnVolume_OnClicked(
  783. QWidget *a_ptbtnVolume
  784. )
  785. {
  786. // wrap window
  787. {
  788. cint ciTitleHeight = ui.frTitle->geometry().height();
  789. cint ciTargetHeight = ciTitleHeight;
  790. setFixedHeight(ciTargetHeight);
  791. }
  792. QToolButton *ptbTB = dynamic_cast<QToolButton *>( a_ptbtnVolume );
  793. xTEST_PTR(ptbTB);
  794. #if defined(Q_OS_WIN)
  795. cQString sVolumePath = ptbTB->text() + ":";
  796. #else
  797. cQString sVolumePath = ptbTB->text();
  798. #endif
  799. qCHECK_DO(!CxVolume( qQS2S(sVolumePath) ).isReady(), return);
  800. bool bRv = QDesktopServices::openUrl( QString("file:///%1").arg(sVolumePath) );
  801. xTEST_EQ(true, bRv);
  802. }
  803. //------------------------------------------------------------------------------
  804. bool
  805. CMain::_volumes_Rebuild(
  806. volume_buttons_t *a_pvtbVolumes
  807. )
  808. {
  809. xTEST_PTR(a_pvtbVolumes);
  810. //--------------------------------------------------
  811. // "My computer" button
  812. {
  813. // icon
  814. {
  815. QIcon icoVolume = QFileIconProvider().icon( QFileIconProvider::Computer );
  816. ui.tbtnMyComputer->setIcon(icoVolume);
  817. }
  818. // tooltip
  819. {
  820. CxSystemInfo info;
  821. std::tstring_t sToolTip = CxString::format(
  822. xT("OS: %s (%s)\n")
  823. xT("Shell: %s\n")
  824. xT("Host: %s\n")
  825. xT("User: %s\n")
  826. xT("Cpu: %s %ld MHz\n")
  827. xT("Ram: %s"),
  828. info.formatOsType().c_str(),
  829. info.formatOsArch().c_str(),
  830. info.desktopName().c_str(),
  831. info.hostName().c_str(),
  832. info.userName().c_str(),
  833. info.cpuModel().c_str(),
  834. info.cpuSpeed(),
  835. CxString::formatBytes( info.ramTotal() ).c_str()
  836. );
  837. ui.tbtnMyComputer->setToolTip( qS2QS(sToolTip) );
  838. }
  839. }
  840. //--------------------------------------------------
  841. // hide volume buttons
  842. for (int i = 0; i < a_pvtbVolumes->size(); ++ i) {
  843. a_pvtbVolumes->at(i)->setVisible(false);
  844. }
  845. //--------------------------------------------------
  846. // build volume buttons
  847. std::vector<std::tstring_t> vsVolumes;
  848. CxVolume::paths(&vsVolumes);
  849. // HACK: when mobile (SE) inserted - QVector<T>::at: "index out of range"
  850. {
  851. std::csize_t ciVolumesMax = 8;
  852. if (ciVolumesMax < vsVolumes.size()) {
  853. vsVolumes.resize(ciVolumesMax);
  854. }
  855. }
  856. for (size_t i = 0; i < vsVolumes.size(); ++ i) {
  857. // text
  858. {
  859. std::tstring_t sCaption = vsVolumes.at(i);
  860. #if defined(Q_OS_WIN)
  861. // remove colon and slash
  862. sCaption.resize(vsVolumes.at(i).size() - std::tstring_t(xT(":\\")).size());
  863. #endif
  864. a_pvtbVolumes->at(i)->setText( qS2QS(sCaption) );
  865. }
  866. // icon
  867. {
  868. QFileIconProvider fipProvider;
  869. QFileInfo fiInfo( qS2QS(vsVolumes.at(i)) );
  870. QIcon icoVolume = fipProvider.icon(fiInfo);
  871. a_pvtbVolumes->at(i)->setIcon(icoVolume);
  872. }
  873. // tooltip
  874. {
  875. std::tstring_t sLabel;
  876. ulonglong_t ullFreeBytesAvailable = 0ULL;
  877. ulonglong_t ullTotalNumberOfBytes = 0ULL;
  878. ulonglong_t ullTotalNumberOfFreeBytes = 0ULL;
  879. bool bRv = CxVolume(vsVolumes.at(i)).isReady();
  880. if (false == bRv) {
  881. sLabel = xT("");
  882. ullFreeBytesAvailable = 0ULL;
  883. ullTotalNumberOfBytes = 0ULL;
  884. ullTotalNumberOfFreeBytes = 0ULL;
  885. } else {
  886. sLabel = CxVolume(vsVolumes.at(i)).label();
  887. CxVolume::space(vsVolumes.at(i),
  888. &ullFreeBytesAvailable,
  889. &ullTotalNumberOfBytes,
  890. &ullTotalNumberOfFreeBytes);
  891. }
  892. std::tstring_t sToolTip = CxString::format(
  893. xT("Label: %s\n")
  894. xT("Total: %s\n")
  895. xT("Free: %s"),
  896. sLabel.c_str(),
  897. CxString::formatBytes(ullTotalNumberOfBytes).c_str(),
  898. CxString::formatBytes(ullTotalNumberOfFreeBytes).c_str()
  899. );
  900. a_pvtbVolumes->at(i)->setToolTip( qS2QS(sToolTip) );
  901. }
  902. // visible
  903. {
  904. a_pvtbVolumes->at(i)->setVisible(true);
  905. }
  906. }
  907. return true;
  908. }
  909. //------------------------------------------------------------------------------
  910. /*******************************************************************************
  911. * menu Dirs
  912. *
  913. *******************************************************************************/
  914. //------------------------------------------------------------------------------
  915. void
  916. CMain::_menuDirs_Create(
  917. QMenu *a_pmnuMenu,
  918. QObject *a_parent
  919. )
  920. {
  921. QString sControlPanelPath;
  922. // get "control.exe" file path (for getting icon)
  923. {
  924. #if defined(Q_OS_WIN)
  925. std::tstring_t sRv;
  926. sRv.resize(xPATH_MAX);
  927. UINT uiRes = ::GetSystemDirectory(&sRv.at(0), sRv.size());
  928. sRv.resize(uiRes);
  929. sRv += CxConst::xSLASH;
  930. sRv += xT("control.exe");
  931. sControlPanelPath = qS2QS(sRv);
  932. #else
  933. #pragma message "TODO: get 'control.exe' file path (for getting icon)"
  934. #endif
  935. }
  936. // get "My documents" dir path (for getting icon)
  937. QString sMyDocumentsPath;
  938. sMyDocumentsPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
  939. // icons
  940. QIcon icoHome = QProxyStyle().standardIcon(QStyle::SP_DirHomeIcon);
  941. QIcon icoDesktop = QFileIconProvider().icon( QFileIconProvider::Desktop );
  942. QIcon icoProgramFiles = QFileIconProvider().icon( QFileIconProvider::Folder );
  943. QIcon icoMyDocuments = QFileIconProvider().icon( QFileInfo(sMyDocumentsPath) );
  944. QIcon icoMyComputer = QFileIconProvider().icon( QFileIconProvider::Computer );
  945. QIcon icoControlPanel = QFileIconProvider().icon( QFileInfo(sControlPanelPath) );
  946. QIcon icoOsCore = QFileIconProvider().icon( QFileIconProvider::Folder );
  947. #if defined(Q_OS_WIN)
  948. QIcon icoAutorun = QFileIconProvider().icon( QFileIconProvider::Folder );
  949. QIcon icoSendTo = QFileIconProvider().icon( QFileIconProvider::Folder );
  950. #endif
  951. QIcon icoTemp = QFileIconProvider().icon( QFileIconProvider::Folder );
  952. QIcon icoNetwork = QFileIconProvider().icon( QFileIconProvider::Network );
  953. QIcon icoTrash = QFileIconProvider().icon( QFileIconProvider::Trashcan );
  954. // actions
  955. QAction *acHome = new QAction(icoHome, tr("Home"), a_parent);
  956. connect(acHome, &QAction::triggered,
  957. this, &CMain::mnuDirs_OnHome);
  958. QAction *acDesktop = new QAction(icoDesktop, tr("Desktop"), a_parent);
  959. connect(acDesktop, &QAction::triggered,
  960. this, &CMain::mnuDirs_OnDesktop);
  961. QAction *acProgramFiles = new QAction(icoProgramFiles, tr("Program files"), a_parent);
  962. connect(acProgramFiles, &QAction::triggered,
  963. this, &CMain::mnuDirs_OnProgramFiles);
  964. QAction *acMyDocuments = new QAction(icoMyDocuments, tr("My documents"), a_parent);
  965. connect(acMyDocuments, &QAction::triggered,
  966. this, &CMain::mnuDirs_OnMyDocuments);
  967. QAction *acMyComputer = new QAction(icoMyComputer, tr("My computer"), a_parent);
  968. connect(acMyComputer, &QAction::triggered,
  969. this, &CMain::mnuDirs_OnMyComputer);
  970. QAction *acControlPanel = new QAction(icoControlPanel, tr("Control panel"), a_parent);
  971. connect(acControlPanel, &QAction::triggered,
  972. this, &CMain::mnuDirs_OnControlPanel);
  973. QAction *acOsCore = new QAction(icoOsCore, tr("OS core"), a_parent);
  974. connect(acOsCore, &QAction::triggered,
  975. this, &CMain::mnuDirs_OnOsCore);
  976. #if defined(Q_OS_WIN)
  977. QAction *acAutorun = new QAction(icoAutorun, tr("Autorun"), a_parent);
  978. connect(acAutorun, &QAction::triggered,
  979. this, &CMain::mnuDirs_OnAutorun);
  980. QAction *acSendTo = new QAction(icoSendTo, tr("Sent to"), a_parent);
  981. connect(acSendTo, &QAction::triggered,
  982. this, &CMain::mnuDirs_OnSendTo);
  983. #endif
  984. QAction *acTemp = new QAction(icoTemp, tr("Temp"), a_parent);
  985. connect(acTemp, &QAction::triggered,
  986. this, &CMain::mnuDirs_OnTemp);
  987. QAction *acNetwork = new QAction(icoNetwork, tr("Network"), a_parent);
  988. connect(acNetwork, &QAction::triggered,
  989. this, &CMain::mnuDirs_OnNetwork);
  990. QAction *acTrash = new QAction(icoTrash, tr("Trash"), a_parent);
  991. connect(acTrash, &QAction::triggered,
  992. this, &CMain::mnuDirs_OnTrash);
  993. // add actions
  994. a_pmnuMenu->addAction(acHome);
  995. a_pmnuMenu->addAction(acDesktop);
  996. a_pmnuMenu->addAction(acProgramFiles);
  997. a_pmnuMenu->addAction(acMyDocuments);
  998. a_pmnuMenu->addAction(acMyComputer);
  999. a_pmnuMenu->addAction(acControlPanel);
  1000. a_pmnuMenu->addAction(acOsCore);
  1001. #if defined(Q_OS_WIN)
  1002. a_pmnuMenu->addAction(acAutorun);
  1003. a_pmnuMenu->addAction(acSendTo);
  1004. #endif
  1005. a_pmnuMenu->addAction(acTemp);
  1006. a_pmnuMenu->addAction(acNetwork);
  1007. a_pmnuMenu->addAction(acTrash);
  1008. }
  1009. //------------------------------------------------------------------------------
  1010. void
  1011. CMain::mnuDirs_OnHome() {
  1012. cQString csDir = QString("file:///%1")
  1013. .arg(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
  1014. bool bRv = QDesktopServices::openUrl(csDir);
  1015. xTEST_EQ(true, bRv);
  1016. }
  1017. //------------------------------------------------------------------------------
  1018. void
  1019. CMain::mnuDirs_OnDesktop() {
  1020. cQString csDir = QString("file:///%1")
  1021. .arg(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
  1022. bool bRv = QDesktopServices::openUrl(csDir);
  1023. xTEST_EQ(true, bRv);
  1024. }
  1025. //------------------------------------------------------------------------------
  1026. void
  1027. CMain::mnuDirs_OnProgramFiles() {
  1028. QString sDir;
  1029. {
  1030. #if defined(Q_OS_WIN)
  1031. LPITEMIDLIST pidl = {0};
  1032. ::SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAM_FILES , &pidl);
  1033. tchar_t szBuff[MAX_PATH + 1] = {0};
  1034. ::SHGetPathFromIDList(pidl, szBuff);
  1035. sDir = QString("file:///") + qS2QS(szBuff);
  1036. #else
  1037. sDir = QString("file:///%1").arg(SPECIAL_DIR_PROGRAM_FILES);
  1038. #endif
  1039. }
  1040. bool bRv = QDesktopServices::openUrl( QUrl(sDir) );
  1041. xTEST_EQ(true, bRv);
  1042. }
  1043. //------------------------------------------------------------------------------
  1044. void
  1045. CMain::mnuDirs_OnMyDocuments() {
  1046. cQString csDir = QString("file:///%1")
  1047. .arg(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
  1048. bool bRv = QDesktopServices::openUrl(csDir);
  1049. xTEST_EQ(true, bRv);
  1050. }
  1051. //------------------------------------------------------------------------------
  1052. void
  1053. CMain::mnuDirs_OnMyComputer() {
  1054. #if defined(Q_OS_WIN)
  1055. LPITEMIDLIST lst = {0};
  1056. SHELLEXECUTEINFO se = {0};
  1057. ::SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &lst);
  1058. se.cbSize = sizeof(se);
  1059. se.fMask = SEE_MASK_IDLIST;
  1060. se.hwnd = NULL;
  1061. se.lpVerb = xT("open");
  1062. se.nShow = SW_SHOW;
  1063. se.lpIDList = lst;
  1064. ::ShellExecuteEx(&se);
  1065. (void)::CoTaskMemFree(lst);
  1066. #else
  1067. cQString csDir = QString("file:///%1").arg(QDir::rootPath());
  1068. bool bRv = QDesktopServices::openUrl( QUrl(csDir) );
  1069. xTEST_EQ(true, bRv);
  1070. #endif
  1071. }
  1072. //------------------------------------------------------------------------------
  1073. void
  1074. CMain::mnuDirs_OnControlPanel() {
  1075. #if defined(Q_OS_WIN)
  1076. LPITEMIDLIST lst = {0};
  1077. SHELLEXECUTEINFO se = {0};
  1078. ::SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &lst);
  1079. se.cbSize = sizeof(se);
  1080. se.fMask = SEE_MASK_IDLIST;
  1081. se.hwnd = NULL;
  1082. se.lpVerb = xT("open");
  1083. se.nShow = SW_SHOW;
  1084. se.lpIDList = lst;
  1085. ::ShellExecuteEx(&se);
  1086. (void)::CoTaskMemFree(lst);
  1087. #else
  1088. QString sFile;
  1089. cQString csDesktop = QString().fromStdString( CxSystemInfo().desktopName() );
  1090. if ("gnome" == csDesktop) {
  1091. sFile = "/usr/bin/gnome-control-center";
  1092. }
  1093. else if ("kde" == csDesktop || "kde-plasma" == csDesktop) {
  1094. sFile = "/usr/bin/systemsettings";
  1095. }
  1096. else if ("xfce" == csDesktop) {
  1097. sFile = "/usr/bin/xfce4-settings-manager";
  1098. }
  1099. else {
  1100. sFile = "";
  1101. }
  1102. qDebug() << qDEBUG_VAR(csDesktop);
  1103. cQString dir = QString("file:///%1").arg(sFile);
  1104. bool bRv = QDesktopServices::openUrl( QUrl(dir) );
  1105. xTEST_EQ(true, bRv);
  1106. #endif
  1107. }
  1108. //------------------------------------------------------------------------------
  1109. void
  1110. CMain::mnuDirs_OnOsCore() {
  1111. QString sDir;
  1112. {
  1113. #if defined(Q_OS_WIN)
  1114. LPITEMIDLIST pidl = {0};
  1115. ::SHGetSpecialFolderLocation(NULL, CSIDL_WINDOWS, &pidl);
  1116. tchar_t szBuff[MAX_PATH + 1] = {0};
  1117. ::SHGetPathFromIDList(pidl, szBuff);
  1118. sDir = QString("file:///%1") + qS2QS(szBuff);
  1119. #else
  1120. sDir = QString("file:///%1").arg(SPECIAL_DIR_OS_CORE);
  1121. #endif
  1122. }
  1123. bool bRv = QDesktopServices::openUrl( QUrl(sDir) );
  1124. xTEST_EQ(true, bRv);
  1125. }
  1126. //------------------------------------------------------------------------------
  1127. #if defined(Q_OS_WIN)
  1128. void
  1129. CMain::mnuDirs_OnAutorun() {
  1130. QString sDir;
  1131. {
  1132. #if defined(Q_OS_WIN)
  1133. LPITEMIDLIST pidl = {0};
  1134. ::SHGetSpecialFolderLocation(NULL, CSIDL_STARTUP, &pidl);
  1135. tchar_t szBuff[MAX_PATH + 1] = {0};
  1136. ::SHGetPathFromIDList(pidl, szBuff);
  1137. sDir = QString("file:///%1") + qS2QS(szBuff);
  1138. #else
  1139. #pragma message "TODO: Unix part"
  1140. #endif
  1141. }
  1142. bool bRv = QDesktopServices::openUrl( QUrl(sDir) );
  1143. xTEST_EQ(true, bRv);
  1144. }
  1145. #endif
  1146. //------------------------------------------------------------------------------
  1147. #if defined(Q_OS_WIN)
  1148. void
  1149. CMain::mnuDirs_OnSendTo() {
  1150. QString sDir;
  1151. {
  1152. LPITEMIDLIST pidl = {0};
  1153. ::SHGetSpecialFolderLocation(NULL, CSIDL_SENDTO, &pidl);
  1154. tchar_t szBuff[MAX_PATH + 1] = {0};
  1155. ::SHGetPathFromIDList(pidl, szBuff);
  1156. sDir = QString("file:///%1") + qS2QS(szBuff);
  1157. }
  1158. bool bRv = QDesktopServices::openUrl( QUrl(sDir) );
  1159. xTEST_EQ(true, bRv);
  1160. }
  1161. #endif
  1162. //------------------------------------------------------------------------------
  1163. void
  1164. CMain::mnuDirs_OnTemp() {
  1165. cQString csDir = QString("file:///%1")
  1166. .arg(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
  1167. bool bRv = QDesktopServices::openUrl( QUrl(csDir) );
  1168. xTEST_EQ(true, bRv);
  1169. }
  1170. //------------------------------------------------------------------------------
  1171. void
  1172. CMain::mnuDirs_OnNetwork() {
  1173. #if defined(Q_OS_WIN)
  1174. LPITEMIDLIST lst = {0};
  1175. SHELLEXECUTEINFO se = {0};
  1176. ::SHGetSpecialFolderLocation(NULL, CSIDL_NETWORK, &lst);
  1177. se.cbSize = sizeof(se);
  1178. se.fMask = SEE_MASK_IDLIST;
  1179. se.hwnd = NULL;
  1180. se.lpVerb = xT("open");
  1181. se.nShow = SW_SHOW;
  1182. se.lpIDList = lst;
  1183. ::ShellExecuteEx(&se);
  1184. (void)::CoTaskMemFree(lst);
  1185. #else
  1186. QString sFile;
  1187. cQString csDesktop = QString().fromStdString( CxSystemInfo().desktopName() );
  1188. if ("gnome" == csDesktop) {
  1189. sFile = "/usr/bin/gnome-network-properties";
  1190. }
  1191. else if ("kde" == csDesktop || "kde-plasma" == csDesktop) {
  1192. #pragma message "TODO: mnuDirs_OnNetwork"
  1193. sFile = "/usr/bin/knetworkmanager";
  1194. }
  1195. else if ("xfce" == csDesktop) {
  1196. #pragma message "TODO: mnuDirs_OnNetwork"
  1197. sFile = "";
  1198. }
  1199. else {
  1200. sFile = "";
  1201. }
  1202. QString sDir = QString("file:///%1").arg(sFile);
  1203. bool bRv = QDesktopServices::openUrl( QUrl(sDir) );
  1204. xTEST_EQ(true, bRv);
  1205. #endif
  1206. }
  1207. //------------------------------------------------------------------------------
  1208. void
  1209. CMain::mnuDirs_OnTrash() {
  1210. #if defined(Q_OS_WIN)
  1211. LPITEMIDLIST lst = {0};
  1212. SHELLEXECUTEINFO se = {0};
  1213. ::SHGetSpecialFolderLocation(NULL, CSIDL_BITBUCKET, &lst);
  1214. se.cbSize = sizeof(se);
  1215. se.fMask = SEE_MASK_IDLIST;
  1216. se.hwnd = NULL;
  1217. se.lpVerb = xT("open");
  1218. se.nShow = SW_SHOW;
  1219. se.lpIDList = lst;
  1220. ::ShellExecuteEx(&se);
  1221. (void)::CoTaskMemFree(lst);
  1222. #else
  1223. cQString csDir = QString("file:///%1/%2")
  1224. .arg(QStandardPaths::standardLocations(QStandardPaths::HomeLocation).toVector().at(0))
  1225. .arg(SPECIAL_RELATIVE_DIR_TRASH);
  1226. bool bRv = QDesktopServices::openUrl( QUrl(csDir) );
  1227. xTEST_EQ(true, bRv);
  1228. #endif
  1229. }
  1230. //------------------------------------------------------------------------------
  1231. /*******************************************************************************
  1232. * _m_tabLinks
  1233. *
  1234. *******************************************************************************/
  1235. //------------------------------------------------------------------------------
  1236. void
  1237. CMain::mnuLinks_OnShow(
  1238. const QPoint &a_point
  1239. )
  1240. {
  1241. _m_bIsAllowWrap = false;
  1242. qCHECK_DO(true == a_point.isNull(), return);
  1243. QMenu mnuLinks(this);
  1244. // actions
  1245. QAction *acTabAdd = new QAction(tr("Tab add"), this);
  1246. connect(acTabAdd, &QAction::triggered,
  1247. this, &CMain::mnuLinks_OnTabAdd);
  1248. QAction *acTabRemove = new QAction(tr("Tab remove"), this);
  1249. connect(acTabRemove, &QAction::triggered,
  1250. this, &CMain::mnuLinks_OnTabRemove);
  1251. QAction *acTabRename = new QAction(tr("Tab rename"), this);
  1252. connect(acTabRename, &QAction::triggered,
  1253. this, &CMain::mnuLinks_OnTabRename);
  1254. // add actions
  1255. mnuLinks.addAction(acTabAdd);
  1256. mnuLinks.addAction(acTabRemove);
  1257. mnuLinks.addAction(acTabRename);
  1258. mnuLinks.exec( _m_tabLinks->mapToGlobal(a_point) );
  1259. _m_bIsAllowWrap = true;
  1260. }
  1261. //------------------------------------------------------------------------------
  1262. void
  1263. CMain::mnuLinks_OnTabAdd() {
  1264. // Get table name
  1265. QString sTabName;
  1266. {
  1267. QInputDialog idlgInputDialog(this);
  1268. cint ciRv = idlgInputDialog.exec();
  1269. switch (ciRv) {
  1270. case QDialog::Rejected:
  1271. return;
  1272. break;
  1273. case QDialog::Accepted:
  1274. qCHECK_DO(true == idlgInputDialog.textValue().isEmpty(), return);
  1275. sTabName = idlgInputDialog.textValue();
  1276. break;
  1277. default:
  1278. xTEST_FAIL;
  1279. break;
  1280. }
  1281. }
  1282. // to UI
  1283. {
  1284. _tabPageAddEmpty(sTabName);
  1285. _tabPageShow(sTabName);
  1286. }
  1287. }
  1288. //------------------------------------------------------------------------------
  1289. void
  1290. CMain::mnuLinks_OnTabRemove() {
  1291. // ask for removing
  1292. {
  1293. cQString csText = tr("Remove the tab and all its content?");
  1294. cint ciRv = QMessageBox::question(this, qApp->applicationName(), csText,
  1295. QMessageBox::Ok | QMessageBox::No);
  1296. switch (ciRv) {
  1297. case QMessageBox::Ok:
  1298. xNA;
  1299. break;
  1300. default:
  1301. case QMessageBox::No:
  1302. return;
  1303. break;
  1304. }
  1305. }
  1306. cQString csTabName = _m_tabLinks->tabText( _m_tabLinks->currentIndex() );
  1307. // to DB
  1308. {
  1309. // from t_tabs
  1310. {
  1311. QSqlQuery qryDelete(_m_dbDatabase);
  1312. cQString csSql = \
  1313. "DELETE FROM t_tabs WHERE f_name=:p_tab_name;";
  1314. bool bRv = qryDelete.prepare(csSql);
  1315. qCHECK_REF(bRv, qryDelete)
  1316. qryDelete.bindValue(":p_tab_name", csTabName);
  1317. bRv = qryDelete.exec();
  1318. qCHECK_REF(bRv, qryDelete);
  1319. }
  1320. // from t_main
  1321. {
  1322. QSqlQuery qryDelete(_m_dbDatabase);
  1323. cQString csSql = \
  1324. "DELETE FROM t_main WHERE f_tab_index=:p_tab_index";
  1325. bool bRv = qryDelete.prepare(csSql);
  1326. qCHECK_REF(bRv, qryDelete)
  1327. qryDelete.bindValue(":p_tab_index", _m_tabLinks->currentIndex());
  1328. bRv = qryDelete.exec();
  1329. qCHECK_REF(bRv, qryDelete);
  1330. }
  1331. }
  1332. // to UI
  1333. {
  1334. _m_tabLinks->removeTab( _m_tabLinks->currentIndex() );
  1335. }
  1336. }
  1337. //------------------------------------------------------------------------------
  1338. void
  1339. CMain::mnuLinks_OnTabRename() {
  1340. bool bRv = false;
  1341. // Get table new name, old name
  1342. QString sTabNameNew;
  1343. QString sTabNameOld;
  1344. {
  1345. QInputDialog idlgInputDialog(this);
  1346. cint ciRv = idlgInputDialog.exec();
  1347. switch (ciRv) {
  1348. case QDialog::Rejected:
  1349. return;
  1350. break;
  1351. case QDialog::Accepted:
  1352. qCHECK_DO(true == idlgInputDialog.textValue().isEmpty(), return);
  1353. sTabNameNew = idlgInputDialog.textValue();
  1354. sTabNameOld = _m_tabLinks->tabText( _m_tabLinks->currentIndex() );
  1355. break;
  1356. default:
  1357. xTEST_FAIL;
  1358. break;
  1359. }
  1360. }
  1361. // to DB
  1362. {
  1363. QSqlQuery qryUpdate(_m_dbDatabase);
  1364. cQString csSql = \
  1365. "UPDATE t_tabs SET f_name=:p_tab_name_new WHERE f_name=:p_tab_name_old";
  1366. bRv = qryUpdate.prepare(csSql);
  1367. qCHECK_REF(bRv, qryUpdate)
  1368. qryUpdate.bindValue(":p_tab_name_new", sTabNameNew);
  1369. qryUpdate.bindValue(":p_tab_name_old", sTabNameOld);
  1370. bRv = qryUpdate.exec();
  1371. qCHECK_REF(bRv, qryUpdate);
  1372. }
  1373. // to UI
  1374. {
  1375. _m_tabLinks->setTabText(_m_tabLinks->currentIndex(), sTabNameNew);
  1376. }
  1377. }
  1378. //------------------------------------------------------------------------------
  1379. void
  1380. CMain::tabLinks_OnMoved(
  1381. int a_from,
  1382. int a_to
  1383. )
  1384. {
  1385. cint ciTabIndexFrom = a_from;
  1386. cint ciTabIndexTo = a_to;
  1387. cint ciTabIndexTemp = - 1; // TODO: ciTabIndexTemp - fix ??
  1388. cQString csTabNameFrom = _m_tabLinks->tabText( ciTabIndexFrom );
  1389. cQString csTabNameTo = _m_tabLinks->tabText( ciTabIndexTo );
  1390. cQString csTabNameTemp = "temp_tab_name_0123456789"; // TODO: csTabNameTemp - fix ??
  1391. bool bRv = false;
  1392. // move in DB (T_MAIN)
  1393. {
  1394. // ciTabIndexFrom = ciTabIndexTemp
  1395. {
  1396. QSqlQuery qryUpdate(_m_dbDatabase);
  1397. cQString csSql = \
  1398. "UPDATE t_main SET f_tab_index=:p_tab_index_new WHERE f_tab_index=:p_tab_index_old";
  1399. bRv = qryUpdate.prepare(csSql);
  1400. qCHECK_REF(bRv, qryUpdate)
  1401. qryUpdate.bindValue(":p_tab_index_new", ciTabIndexTemp);
  1402. qryUpdate.bindValue(":p_tab_index_old", ciTabIndexFrom);
  1403. bRv = qryUpdate.exec();
  1404. qCHECK_REF(bRv, qryUpdate);
  1405. }
  1406. // ciTabIndexTo = ciTabIndexFrom
  1407. {
  1408. QSqlQuery qryUpdate(_m_dbDatabase);
  1409. cQString csSql = \
  1410. "UPDATE t_main SET f_tab_index=:p_tab_index_new WHERE f_tab_index=:p_tab_index_old";
  1411. bRv = qryUpdate.prepare(csSql);
  1412. qCHECK_REF(bRv, qryUpdate)
  1413. qryUpdate.bindValue(":p_tab_index_new", ciTabIndexFrom);
  1414. qryUpdate.bindValue(":p_tab_index_old", ciTabIndexTo);
  1415. bRv = qryUpdate.exec();
  1416. qCHECK_REF(bRv, qryUpdate);
  1417. }
  1418. // ciTabIndexTemp = ciTabIndexTo
  1419. {
  1420. QSqlQuery qryUpdate(_m_dbDatabase);
  1421. cQString csSql = \
  1422. "UPDATE t_main SET f_tab_index=:p_tab_index_new WHERE f_tab_index=:p_tab_index_old";
  1423. bRv = qryUpdate.prepare(csSql);
  1424. qCHECK_REF(bRv, qryUpdate)
  1425. qryUpdate.bindValue(":p_tab_index_new", ciTabIndexTo);
  1426. qryUpdate.bindValue(":p_tab_index_old", ciTabIndexTemp);
  1427. bRv = qryUpdate.exec();
  1428. qCHECK_REF(bRv, qryUpdate);
  1429. }
  1430. }
  1431. // move in DB (T_TABS)
  1432. {
  1433. // csTabNameFrom = csTabNameTemp
  1434. {
  1435. QSqlQuery qryUpdate(_m_dbDatabase);
  1436. cQString csSql = \
  1437. "UPDATE t_tabs SET f_name=:p_tab_name_new WHERE f_name=:p_tab_name_old";
  1438. bRv = qryUpdate.prepare(csSql);
  1439. qCHECK_REF(bRv, qryUpdate)
  1440. qryUpdate.bindValue(":p_tab_name_new", csTabNameTemp);
  1441. qryUpdate.bindValue(":p_tab_name_old", csTabNameFrom);
  1442. bRv = qryUpdate.exec();
  1443. qCHECK_REF(bRv, qryUpdate);
  1444. }
  1445. // csTabNameTo = csTabNameFrom
  1446. {
  1447. QSqlQuery qryUpdate(_m_dbDatabase);
  1448. cQString csSql = \
  1449. "UPDATE t_tabs SET f_name=:p_tab_name_new WHERE f_name=:p_tab_name_old";
  1450. bRv = qryUpdate.prepare(csSql);
  1451. qCHECK_REF(bRv, qryUpdate)
  1452. qryUpdate.bindValue(":p_tab_name_new", csTabNameFrom);
  1453. qryUpdate.bindValue(":p_tab_name_old", csTabNameTo);
  1454. bRv = qryUpdate.exec();
  1455. qCHECK_REF(bRv, qryUpdate);
  1456. }
  1457. // csTabNameTemp = csTabNameTo
  1458. {
  1459. QSqlQuery qryUpdate(_m_dbDatabase);
  1460. cQString csSql = \
  1461. "UPDATE t_tabs SET f_name=:p_tab_name_new WHERE f_name=:p_tab_name_old";
  1462. bRv = qryUpdate.prepare(csSql);
  1463. qCHECK_REF(bRv, qryUpdate)
  1464. qryUpdate.bindValue(":p_tab_name_new", csTabNameTo);
  1465. qryUpdate.bindValue(":p_tab_name_old", csTabNameTemp);
  1466. bRv = qryUpdate.exec();
  1467. qCHECK_REF(bRv, qryUpdate);
  1468. }
  1469. }
  1470. // move in UI
  1471. {
  1472. xNA;
  1473. }
  1474. }
  1475. //------------------------------------------------------------------------------
  1476. /*******************************************************************************
  1477. * btnLink
  1478. *
  1479. *******************************************************************************/
  1480. //------------------------------------------------------------------------------
  1481. void
  1482. CMain::btnLink_OnClicked(
  1483. QWidget *a_pwdgWidget
  1484. )
  1485. {
  1486. CLinkButton *pbtnSender = dynamic_cast<CLinkButton *>( a_pwdgWidget );
  1487. xTEST_PTR(pbtnSender);
  1488. // swap shortcuts
  1489. if (true == _m_bIsLinkSwap) {
  1490. cint ciFromTabIndex = _m_btnLinkFrom->tabIndex();
  1491. cint ciFromLinkIndex = _m_btnLinkFrom->linkIndex();
  1492. cQString csFromText = _m_btnLinkFrom->text().trimmed();
  1493. cQString csFromFilePath = _m_btnLinkFrom->filePath().trimmed();
  1494. cQString csFromFileParams = _m_btnLinkFrom->fileParams().trimmed();
  1495. cint ciToTabIndex = pbtnSender->tabIndex();
  1496. cint ciToLinkIndex = pbtnSender->linkIndex();
  1497. cQString csToText = pbtnSender->text().trimmed();
  1498. cQString csToFilePath = pbtnSender->filePath().trimmed();
  1499. cQString csToFileParams = pbtnSender->fileParams().trimmed();
  1500. cint ciTempLinkIndex = - 1; // TODO: ciTempLinkIndex - fix ??
  1501. xTEST_EQ(ciToTabIndex, ciFromTabIndex);
  1502. xTEST_DIFF(ciFromLinkIndex, ciToLinkIndex);
  1503. xTEST_LESS(- 1, ciToTabIndex);
  1504. xTEST_LESS(- 1, ciToLinkIndex);
  1505. xTEST_LESS(- 1, ciFromTabIndex);
  1506. xTEST_LESS(- 1, ciFromLinkIndex);
  1507. // qDebug() << "[" << ciFromTabIndex << ciFromLinkIndex << "] -> [" << ciToTabIndex << ciToLinkIndex << "]";
  1508. // DB (F_MAIN_INDEX)
  1509. {
  1510. // ciFromLinkIndex <= ciTempLinkIndex
  1511. {
  1512. QSqlQuery qryUpdate(_m_dbDatabase);
  1513. cQString csSql = \
  1514. "UPDATE "
  1515. " t_main "
  1516. "SET "
  1517. " f_link_index=:p_link_index_new "
  1518. "WHERE "
  1519. " (f_tab_index=:p_tab_index AND f_link_index=:p_link_index_old)";
  1520. bool bRv = qryUpdate.prepare(csSql);
  1521. qCHECK_REF(bRv, qryUpdate)
  1522. qryUpdate.bindValue(":p_link_index_new", ciTempLinkIndex); // на что
  1523. qryUpdate.bindValue(":p_link_index_old", ciFromLinkIndex); // что
  1524. qryUpdate.bindValue(":p_tab_index", ciFromTabIndex);
  1525. bRv = qryUpdate.exec();
  1526. qCHECK_REF(bRv, qryUpdate);
  1527. }
  1528. // ciToLinkIndex <= ciFromLinkIndex
  1529. {
  1530. QSqlQuery qryUpdate(_m_dbDatabase);
  1531. cQString csSql = \
  1532. "UPDATE "
  1533. " t_main "
  1534. "SET "
  1535. " f_link_index=:p_link_index_new "
  1536. "WHERE "
  1537. " (f_tab_index=:p_tab_index AND f_link_index=:p_link_index_old)";
  1538. bool bRv = qryUpdate.prepare(csSql);
  1539. qCHECK_REF(bRv, qryUpdate)
  1540. qryUpdate.bindValue(":p_link_index_new", ciFromLinkIndex); // на что
  1541. qryUpdate.bindValue(":p_link_index_old", ciToLinkIndex); // что
  1542. qryUpdate.bindValue(":p_tab_index", ciToTabIndex);
  1543. bRv = qryUpdate.exec();
  1544. qCHECK_REF(bRv, qryUpdate);
  1545. }
  1546. // ciTempLinkIndex <= ciToLinkIndex
  1547. {
  1548. QSqlQuery qryUpdate(_m_dbDatabase);
  1549. cQString csSql = \
  1550. "UPDATE "
  1551. " t_main "
  1552. "SET "
  1553. " f_link_index=:p_link_index_new "
  1554. "WHERE "
  1555. " (f_tab_index=:p_tab_index AND f_link_index=:p_link_index_old)";
  1556. bool bRv = qryUpdate.prepare(csSql);
  1557. qCHECK_REF(bRv, qryUpdate)
  1558. qryUpdate.bindValue(":p_link_index_new", ciToLinkIndex); // на что
  1559. qryUpdate.bindValue(":p_link_index_old", ciTempLinkIndex); // что
  1560. qryUpdate.bindValue(":p_tab_index", ciFromTabIndex);
  1561. bRv = qryUpdate.exec();
  1562. qCHECK_REF(bRv, qryUpdate);
  1563. }
  1564. }
  1565. // UI
  1566. {
  1567. {
  1568. _linkUpdate(_m_btnLinkFrom, ciToTabIndex, ciToLinkIndex,
  1569. csToText, csToFilePath, csToFileParams);
  1570. // swap _m_btnLinkFrom <-> pbtnSender
  1571. cint temp = _m_btnLinkFrom->tabIndex();
  1572. _m_btnLinkFrom->setTabIndex(pbtnSender->tabIndex());
  1573. pbtnSender->setTabIndex(temp);
  1574. }
  1575. {
  1576. _linkUpdate(pbtnSender, ciFromTabIndex, ciFromLinkIndex,
  1577. csFromText, csFromFilePath, csFromFileParams);
  1578. // swap _m_btnLinkFrom <-> pbtnSender
  1579. cint temp = _m_btnLinkFrom->linkIndex();
  1580. _m_btnLinkFrom->setLinkIndex(pbtnSender->linkIndex());
  1581. pbtnSender->setLinkIndex(temp);
  1582. }
  1583. }
  1584. // finished
  1585. {
  1586. setCursor( QCursor(Qt::ArrowCursor) );
  1587. _m_btnLinkFrom = NULL;
  1588. _m_bIsLinkSwap = false;
  1589. }
  1590. return;
  1591. } // if (true == _m_bIsLinkSwap)
  1592. // execute program
  1593. {
  1594. cQString csFilePath = pbtnSender->filePath().trimmed();
  1595. cQString csFileParams = pbtnSender->fileParams().trimmed(); // TODO: csFileParams
  1596. qCHECK_DO(true == csFilePath.isEmpty(), return);
  1597. cQString csDir = QString("file:///%1").arg(csFilePath);
  1598. bool bRv = QDesktopServices::openUrl( QUrl(csDir) );
  1599. xTEST_EQ(true, bRv);
  1600. }
  1601. }
  1602. //------------------------------------------------------------------------------
  1603. void
  1604. CMain::mnuLink_OnShow(
  1605. const QPoint &a_point
  1606. )
  1607. {
  1608. _m_bIsAllowWrap = false;
  1609. qCHECK_DO(true == a_point.isNull(), return);
  1610. QWidget *pwdgSender = dynamic_cast<QWidget *>( QObject::sender() );
  1611. QMenu mnuShortcut(this);
  1612. // actions
  1613. QAction *acRun = new QAction(tr("Run"), pwdgSender);
  1614. connect(acRun, &QAction::triggered,
  1615. this, &CMain::mnuLink_OnRun);
  1616. QAction *acSwap = new QAction(tr("Swap"), pwdgSender);
  1617. connect(acSwap, &QAction::triggered,
  1618. this, &CMain::mnuLink_OnSwap);
  1619. QAction *acClear = new QAction(tr("Clear"), pwdgSender);
  1620. connect(acClear, &QAction::triggered,
  1621. this, &CMain::mnuLink_OnClear);
  1622. QAction *acFindObject = new QAction(tr("Find object"), pwdgSender);
  1623. connect(acFindObject, &QAction::triggered,
  1624. this, &CMain::mnuLink_OnFindObject);
  1625. QAction *acCopyPathToClip = new QAction(tr("Copy path to clipboard"), pwdgSender);
  1626. connect(acCopyPathToClip, &QAction::triggered,
  1627. this, &CMain::mnuLink_OnCopyPathToClip);
  1628. QAction *acCreateLink = new QAction(tr("Create link"), pwdgSender);
  1629. connect(acCreateLink, &QAction::triggered,
  1630. this, &CMain::mnuLink_OnCreateLink);
  1631. QAction *acProperties = new QAction(tr("Properties"), pwdgSender);
  1632. connect(acProperties, &QAction::triggered,
  1633. this, &CMain::mnuLink_OnProperties);
  1634. // add actions
  1635. mnuShortcut.addAction(acRun);
  1636. mnuShortcut.addSeparator();
  1637. mnuShortcut.addAction(acSwap);
  1638. mnuShortcut.addAction(acClear);
  1639. mnuShortcut.addAction(acFindObject);
  1640. mnuShortcut.addAction(acCopyPathToClip);
  1641. mnuShortcut.addAction(acCreateLink);
  1642. mnuShortcut.addSeparator();
  1643. mnuShortcut.addAction(acProperties);
  1644. mnuShortcut.exec( pwdgSender->mapToGlobal(a_point) );
  1645. _m_bIsAllowWrap = true;
  1646. }
  1647. //------------------------------------------------------------------------------
  1648. void
  1649. CMain::mnuLink_OnRun() {
  1650. QAction *pactSender = dynamic_cast<QAction *>( QObject::sender() );
  1651. xTEST_PTR(pactSender);
  1652. CLinkButton *psbtnParent = dynamic_cast<CLinkButton *>( pactSender->parent() );
  1653. xTEST_PTR(psbtnParent);
  1654. btnLink_OnClicked(psbtnParent);
  1655. }
  1656. //------------------------------------------------------------------------------
  1657. void
  1658. CMain::mnuLink_OnSwap() {
  1659. QAction *pactSender = dynamic_cast<QAction *>( QObject::sender() );
  1660. xTEST_PTR(pactSender);
  1661. CLinkButton *psbtnParent = dynamic_cast<CLinkButton *>( pactSender->parent() );
  1662. xTEST_PTR(psbtnParent);
  1663. // set swap data
  1664. {
  1665. xTEST_PTR_FAIL(_m_btnLinkFrom);
  1666. xTEST_EQ(false, _m_bIsLinkSwap);
  1667. setCursor( QCursor(Qt::PointingHandCursor) );
  1668. _m_btnLinkFrom = psbtnParent;
  1669. _m_bIsLinkSwap = true;
  1670. }
  1671. }
  1672. //------------------------------------------------------------------------------
  1673. void
  1674. CMain::mnuLink_OnClear() {
  1675. QAction *pactSender = dynamic_cast<QAction *>( QObject::sender() );
  1676. xTEST_PTR(pactSender);
  1677. CLinkButton *psbtnParent = dynamic_cast<CLinkButton *>( pactSender->parent() );
  1678. xTEST_PTR(psbtnParent);
  1679. // to UI
  1680. {
  1681. _linkUpdate(psbtnParent, psbtnParent->tabIndex(), psbtnParent->linkIndex(), "", "", "");
  1682. }
  1683. // to DB
  1684. {
  1685. QSqlQuery qryClear(_m_dbDatabase);
  1686. cQString csSql = \
  1687. "UPDATE "
  1688. " t_main "
  1689. "SET "
  1690. " f_text=:p_text, f_file_path=:p_file_path, f_file_params=:p_file_params "
  1691. "WHERE "
  1692. " (f_tab_index=:p_tab_index AND f_link_index=:p_link_index)";
  1693. bool bRv = qryClear.prepare(csSql);
  1694. qCHECK_REF(bRv, qryClear)
  1695. qryClear.bindValue(":p_text", "");
  1696. qryClear.bindValue(":p_file_path", "");
  1697. qryClear.bindValue(":p_file_params", "");
  1698. qryClear.bindValue(":p_tab_index", psbtnParent->tabIndex());
  1699. qryClear.bindValue(":p_link_index", psbtnParent->linkIndex());
  1700. bRv = qryClear.exec();
  1701. qCHECK_REF(bRv, qryClear);
  1702. }
  1703. }
  1704. //------------------------------------------------------------------------------
  1705. void
  1706. CMain::mnuLink_OnFindObject() {
  1707. QAction *pactSender = dynamic_cast<QAction *>( QObject::sender() );
  1708. xTEST_PTR(pactSender);
  1709. CLinkButton *psbtnParent = dynamic_cast<CLinkButton *>( pactSender->parent() );
  1710. xTEST_PTR(psbtnParent);
  1711. #if defined(Q_OS_WIN)
  1712. // NOTE: this works - C:\Windows\explorer.exe /select,"Z:\Coding\Class builder\ClassBuilder.exe"
  1713. QString sExplorer;
  1714. QStringList slParams;
  1715. sExplorer = qS2QS(CxPath( CxEnvironment::var(xT("windir")) ).slashAppend()) + "explorer.exe";
  1716. slParams << QLatin1String("/e,/select,") << QDir::toNativeSeparators( psbtnParent->filePath() );
  1717. QProcess::startDetached(sExplorer, slParams);
  1718. #elif defined(Q_OS_MAC)
  1719. QStringList scriptArgs;
  1720. scriptArgs << QLatin1String("-e")
  1721. << QString::fromLatin1("tell application \"Finder\" to reveal POSIX file \"%1\"")
  1722. .arg(pathIn);
  1723. QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs);
  1724. scriptArgs.clear();
  1725. scriptArgs << QLatin1String("-e")
  1726. << QLatin1String("tell application \"Finder\" to activate");
  1727. QProcess::execute("/usr/bin/osascript", scriptArgs);
  1728. #else
  1729. // TODO: mnuLink_OnFindObject
  1730. #pragma message "TODO: CMain::mnuLink_OnFindObject"
  1731. #endif
  1732. }
  1733. //------------------------------------------------------------------------------
  1734. void
  1735. CMain::mnuLink_OnCopyPathToClip() {
  1736. QAction *pactSender = dynamic_cast<QAction *>( QObject::sender() );
  1737. xTEST_PTR(pactSender);
  1738. CLinkButton *psbtnParent = dynamic_cast<CLinkButton *>( pactSender->parent() );
  1739. xTEST_PTR(psbtnParent);
  1740. QClipboard *pcbClipboard = QApplication::clipboard();
  1741. xTEST_PTR(pcbClipboard);
  1742. pcbClipboard->setText(psbtnParent->filePath());
  1743. }
  1744. //------------------------------------------------------------------------------
  1745. void
  1746. CMain::mnuLink_OnCreateLink() {
  1747. QAction *pactSender = dynamic_cast<QAction *>( QObject::sender() );
  1748. xTEST_PTR(pactSender);
  1749. CLinkButton *psbtnParent = dynamic_cast<CLinkButton *>( pactSender->parent() );
  1750. xTEST_PTR(psbtnParent);
  1751. QFileDialog fdlgDialog(this);
  1752. fdlgDialog.setAcceptMode(QFileDialog::AcceptSave);
  1753. fdlgDialog.setFileMode(QFileDialog::AnyFile);
  1754. fdlgDialog.selectFile( QFileInfo(psbtnParent->filePath()).baseName() );
  1755. fdlgDialog.setDefaultSuffix(SHORTCUT_EXT);
  1756. cint ciRv = fdlgDialog.exec();
  1757. switch (ciRv) {
  1758. case QDialog::Rejected:
  1759. xNA;
  1760. break;
  1761. case QDialog::Accepted: {
  1762. cQString csFilePath = fdlgDialog.selectedFiles().first();
  1763. QFile::link(psbtnParent->filePath(), csFilePath);
  1764. }
  1765. break;
  1766. default:
  1767. xTEST_FAIL;
  1768. break;
  1769. }
  1770. }
  1771. //------------------------------------------------------------------------------
  1772. void
  1773. CMain::mnuLink_OnProperties() {
  1774. QAction *pactSender = dynamic_cast<QAction *>( QObject::sender() );
  1775. xTEST_PTR(pactSender);
  1776. CLinkButton *psbtnParent = dynamic_cast<CLinkButton *>( pactSender->parent() );
  1777. xTEST_PTR(psbtnParent);
  1778. CLinkProperties lpProps(this);
  1779. // get
  1780. {
  1781. lpProps.setWindowTitle("Properties");
  1782. lpProps.ui.ledtText->setText ( psbtnParent->text() );
  1783. lpProps.ui.ledtFilePath->setText( psbtnParent->filePath() );
  1784. lpProps.ui.ledtParams->setText ( psbtnParent->fileParams() );
  1785. }
  1786. // show dialog
  1787. QDialog::DialogCode dcRes = static_cast<QDialog::DialogCode>( lpProps.exec() );
  1788. switch (dcRes) {
  1789. case Rejected:
  1790. xNA;
  1791. break;
  1792. case Accepted:
  1793. // to UI
  1794. {
  1795. _linkUpdate(psbtnParent, _m_tabLinks->currentIndex(), psbtnParent->linkIndex(),
  1796. lpProps.ui.ledtText->text(), lpProps.ui.ledtFilePath->text(),
  1797. lpProps.ui.ledtParams->text());
  1798. }
  1799. // to DB
  1800. {
  1801. // update (rename)
  1802. QSqlQuery qryUpdate(_m_dbDatabase);
  1803. cQString csSql = \
  1804. "UPDATE "
  1805. " t_main "
  1806. "SET "
  1807. " f_tab_index=:p_tab_index, f_link_index=:p_link_index, f_text=:p_text, f_file_path=:p_file_path, f_file_params=:p_file_params "
  1808. "WHERE "
  1809. " (f_tab_index=:p_tab_index_old AND f_link_index=:p_link_index_old)";
  1810. bool bRv = qryUpdate.prepare(csSql);
  1811. qCHECK_REF(bRv, qryUpdate)
  1812. qryUpdate.bindValue(":p_tab_index", _m_tabLinks->currentIndex());
  1813. qryUpdate.bindValue(":p_link_index", psbtnParent->linkIndex());
  1814. qryUpdate.bindValue(":p_text", lpProps.ui.ledtText->text());
  1815. qryUpdate.bindValue(":p_file_path", lpProps.ui.ledtFilePath->text());
  1816. qryUpdate.bindValue(":p_file_params", lpProps.ui.ledtParams->text());
  1817. qryUpdate.bindValue(":p_tab_index_old", psbtnParent->tabIndex());
  1818. qryUpdate.bindValue(":p_link_index_old", psbtnParent->linkIndex());
  1819. bRv = qryUpdate.exec();
  1820. qCHECK_REF(bRv, qryUpdate);
  1821. }
  1822. break;
  1823. default:
  1824. xTEST_FAIL;
  1825. break;
  1826. }
  1827. }
  1828. //------------------------------------------------------------------------------
  1829. /*******************************************************************************
  1830. * drag window without title bar
  1831. *
  1832. *******************************************************************************/
  1833. //------------------------------------------------------------------------------
  1834. void
  1835. CMain::mousePressEvent(
  1836. QMouseEvent *a_event
  1837. )
  1838. {
  1839. _m_ptMousePos = a_event->pos();
  1840. }
  1841. //------------------------------------------------------------------------------
  1842. void
  1843. CMain::mouseMoveEvent(
  1844. QMouseEvent *a_event
  1845. )
  1846. {
  1847. if (a_event->buttons() & Qt::LeftButton) {
  1848. QPoint diffPos = a_event->pos() - _m_ptMousePos;
  1849. QPoint newPos = pos() + diffPos;
  1850. move(newPos);
  1851. }
  1852. }
  1853. //------------------------------------------------------------------------------