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

/zuluMount-gui/mainwindow.cpp

https://gitlab.com/m.schmidt/zuluCrypt
C++ | 1219 lines | 882 code | 293 blank | 44 comment | 97 complexity | deb17ed51be903c5dfbebf546cb6b9e1 MD5 | raw file
Possible License(s): BSD-3-Clause-No-Nuclear-License-2014, BSD-2-Clause
  1. /*
  2. *
  3. * Copyright (c) 2012-2015
  4. * name : Francis Banyikwa
  5. * email: mhogomchungu@gmail.com
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "mainwindow.h"
  20. #include "ui_mainwindow.h"
  21. #include <QDebug>
  22. #include <QMainWindow>
  23. #include <QTableWidgetItem>
  24. #include <QDir>
  25. #include <QIcon>
  26. #include <QAction>
  27. #include <QKeySequence>
  28. #include <QSystemTrayIcon>
  29. #include <QMenu>
  30. #include <QCloseEvent>
  31. #include <QFont>
  32. #include <QCursor>
  33. #include <QAction>
  34. #include <QFileDialog>
  35. #include <QUrl>
  36. #include <QTranslator>
  37. #include <QMimeData>
  38. #include <QFile>
  39. #include <utility>
  40. #include <initializer_list>
  41. #include <unistd.h>
  42. #include "keydialog.h"
  43. #include "../zuluCrypt-gui/dialogmsg.h"
  44. #include "../zuluCrypt-gui/tablewidget.h"
  45. #include "mountpartition.h"
  46. #include "oneinstance.h"
  47. #include "events.h"
  48. #include "monitor_mountinfo.h"
  49. #include "../zuluCrypt-gui/utility.h"
  50. #include "zulumounttask.h"
  51. #include "../zuluCrypt-gui/task.h"
  52. #include "../zuluCrypt-gui/checkforupdates.h"
  53. #include <memory>
  54. MainWindow::MainWindow( QWidget * parent ) : QWidget( parent )
  55. {
  56. }
  57. void MainWindow::setUpApp( const QString& volume )
  58. {
  59. this->setLocalizationLanguage() ;
  60. m_ui = new Ui::MainWindow ;
  61. m_ui->setupUi( this ) ;
  62. m_ui->pbunlockencfs->setMinimumHeight( 31 ) ;
  63. m_ui->pbmenu->setMinimumHeight( 31 ) ;
  64. m_ui->pbmount->setMinimumHeight( 31 ) ;
  65. m_ui->pbupdate->setMinimumHeight( 31 ) ;
  66. QVector<int> f = utility::getWindowDimensions( "zuluMount" ) ;
  67. int * e = f.data() ;
  68. this->window()->setGeometry( *( e + 0 ),*( e + 1 ),*( e + 2 ),*( e + 3 ) ) ;
  69. QTableWidget * table = m_ui->tableWidget ;
  70. table->setColumnWidth( 0,*( e + 4 ) ) ;
  71. table->setColumnWidth( 1,*( e + 5 ) ) ;
  72. table->setColumnWidth( 2,*( e + 6 ) ) ;
  73. table->setColumnWidth( 4,*( e + 7 ) ) ;
  74. table->setColumnWidth( 5,*( e + 8 ) ) ;
  75. m_ui->tableWidget->hideColumn( 3 ) ;
  76. #if QT_VERSION < QT_VERSION_CHECK( 5,0,0 )
  77. m_ui->tableWidget->verticalHeader()->setResizeMode( QHeaderView::ResizeToContents ) ;
  78. #else
  79. m_ui->tableWidget->verticalHeader()->setSectionResizeMode( QHeaderView::ResizeToContents ) ;
  80. #endif
  81. m_ui->tableWidget->verticalHeader()->setMinimumSectionSize( 30 ) ;
  82. this->setAcceptDrops( true ) ;
  83. this->setWindowIcon( QIcon( ":/zuluMount.png" ) ) ;
  84. m_ui->tableWidget->setMouseTracking( true ) ;
  85. connect( m_ui->tableWidget,SIGNAL( itemEntered( QTableWidgetItem * ) ),this,SLOT( itemEntered( QTableWidgetItem * ) ) ) ;
  86. connect( m_ui->tableWidget,SIGNAL( currentItemChanged( QTableWidgetItem *,QTableWidgetItem * ) ),
  87. this,SLOT( slotCurrentItemChanged( QTableWidgetItem *,QTableWidgetItem * ) ) ) ;
  88. connect( m_ui->pbmount,SIGNAL( clicked() ),this,SLOT( pbMount() ) ) ;
  89. connect( m_ui->pbupdate,SIGNAL( clicked()),this,SLOT( pbUpdate() ) ) ;
  90. connect( m_ui->pbmenu,SIGNAL( clicked() ),this,SLOT( pbMenu() ) ) ;
  91. connect( m_ui->tableWidget,SIGNAL( itemClicked( QTableWidgetItem * ) ),this,SLOT( itemClicked( QTableWidgetItem * ) ) ) ;
  92. connect( m_ui->pbunlockencfs,SIGNAL( clicked() ),this,SLOT( unlockencfs() ) ) ;
  93. connect( this,SIGNAL( unlistVolume( QString ) ),this,SLOT( removeVolume( QString ) ) ) ;
  94. this->setUpShortCuts() ;
  95. this->setUpFont() ;
  96. m_trayIcon = new QSystemTrayIcon( this ) ;
  97. m_trayIcon->setIcon( QIcon( ":/zuluMount.png" ) ) ;
  98. auto trayMenu = new QMenu( this ) ;
  99. m_autoMountAction = new QAction( this ) ;
  100. m_autoMount = this->autoMount() ;
  101. m_autoMountAction->setCheckable( true ) ;
  102. m_autoMountAction->setChecked( m_autoMount ) ;
  103. m_autoMountAction->setText( tr( "Automount Volumes" ) ) ;
  104. connect( m_autoMountAction,SIGNAL( toggled( bool ) ),this,SLOT( autoMountToggled( bool ) ) ) ;
  105. trayMenu->addAction( m_autoMountAction ) ;
  106. auto autoOpenFolderOnMount = new QAction( this ) ;
  107. autoOpenFolderOnMount->setCheckable( true ) ;
  108. m_autoOpenFolderOnMount = this->autoOpenFolderOnMount() ;
  109. autoOpenFolderOnMount->setChecked( m_autoOpenFolderOnMount ) ;
  110. autoOpenFolderOnMount->setText( tr( "Auto Open Mount Point" ) ) ;
  111. connect( autoOpenFolderOnMount,SIGNAL( toggled( bool ) ),this,SLOT( autoOpenFolderOnMount( bool ) ) ) ;
  112. trayMenu->addAction( autoOpenFolderOnMount ) ;
  113. auto ac = new QAction( this ) ;
  114. ac->setText( tr( "Unmount All" ) ) ;
  115. connect( ac,SIGNAL( triggered() ),this,SLOT( unMountAll() ) ) ;
  116. trayMenu->addAction( ac ) ;
  117. m_favorite_menu = trayMenu->addMenu( tr( "Favorites" ) ) ;
  118. connect( m_favorite_menu,SIGNAL( triggered( QAction * ) ),this,SLOT( favoriteClicked( QAction * ) ) ) ;
  119. connect( m_favorite_menu,SIGNAL( aboutToShow() ),this,SLOT( showFavorites() ) ) ;
  120. m_not_hidden_volume_menu = trayMenu->addMenu( tr( "Hide Volume From View" ) ) ;
  121. connect( m_not_hidden_volume_menu,SIGNAL( triggered( QAction * ) ),this,SLOT( removeVolumeFromVisibleVolumeList( QAction * ) ) ) ;
  122. connect( m_not_hidden_volume_menu,SIGNAL( aboutToShow() ),this,SLOT( showVisibleVolumeList() ) ) ;
  123. m_hidden_volume_menu = trayMenu->addMenu( tr( "Unhide Volume From View" ) ) ;
  124. connect( m_hidden_volume_menu,SIGNAL( triggered( QAction * ) ),this,SLOT( removeVolumeFromHiddenVolumeList( QAction * ) ) ) ;
  125. connect( m_hidden_volume_menu,SIGNAL( aboutToShow() ),this,SLOT( showHiddenVolumeList() ) ) ;
  126. ac = new QAction( this ) ;
  127. ac->setText( tr( "Check For Update" ) ) ;
  128. connect( ac,SIGNAL( triggered() ),this,SLOT( updateCheck() ) ) ;
  129. trayMenu->addAction( ac ) ;
  130. ac = new QAction( this ) ;
  131. ac->setText( tr( "About" ) ) ;
  132. connect( ac,SIGNAL( triggered() ),this,SLOT( licenseInfo() ) ) ;
  133. trayMenu->addAction( ac ) ;
  134. trayMenu->addAction( tr( "Quit" ),this,SLOT( closeApplication() ) ) ;
  135. m_trayIcon->setContextMenu( trayMenu ) ;
  136. connect( m_trayIcon,SIGNAL( activated( QSystemTrayIcon::ActivationReason ) ),
  137. this,SLOT( slotTrayClicked( QSystemTrayIcon::ActivationReason ) ) ) ;
  138. m_ui->pbmenu->setMenu( m_trayIcon->contextMenu() ) ;
  139. m_trayIcon->show() ;
  140. QString dirPath = utility::homePath() + "/.zuluCrypt/" ;
  141. QDir dir( dirPath ) ;
  142. if( !dir.exists() ){
  143. dir.mkdir( dirPath ) ;
  144. }
  145. this->disableAll() ;
  146. this->startAutoMonitor() ;
  147. this->updateVolumeList( zuluMountTask::updateVolumeList().await() ) ;
  148. if( volume.isEmpty() ) {
  149. this->enableAll() ;
  150. }else{
  151. this->showMoungDialog( volume ) ;
  152. }
  153. this->autoUpdateCheck() ;
  154. }
  155. void MainWindow::licenseInfo()
  156. {
  157. utility::licenseInfo( this ) ;
  158. }
  159. void MainWindow::updateCheck()
  160. {
  161. checkForUpdates::checkForUpdate( this ) ;
  162. }
  163. void MainWindow::autoUpdateCheck()
  164. {
  165. checkForUpdates::autoCheckForUpdate( this,"zuluMount" ) ;
  166. }
  167. void MainWindow::removeVolumeFromHiddenVolumeList( QAction * ac )
  168. {
  169. this->disableAll() ;
  170. auto e = ac->text() ;
  171. e.remove( "&" ) ;
  172. zuluMountTask::removeVolumeFromHiddenVolumeList( e ) ;
  173. this->updateList( zuluMountTask::getVolumeProperties( e ).await() ) ;
  174. this->enableAll() ;
  175. }
  176. void MainWindow::showHiddenVolumeList()
  177. {
  178. m_hidden_volume_menu->clear() ;
  179. QStringList l = zuluMountTask::hiddenVolumeList() ;
  180. if( l.isEmpty() ){
  181. auto ac = new QAction( tr( "List Is Empty" ),m_hidden_volume_menu ) ;
  182. ac->setEnabled( false ) ;
  183. m_hidden_volume_menu->addAction( ac ) ;
  184. }else{
  185. for( const auto& it : l ){
  186. auto ac = new QAction( it,m_hidden_volume_menu ) ;
  187. m_hidden_volume_menu->addAction( ac ) ;
  188. }
  189. }
  190. }
  191. void MainWindow::showVisibleVolumeList()
  192. {
  193. m_not_hidden_volume_menu->clear() ;
  194. QStringList l = tablewidget::tableColumnEntries( m_ui->tableWidget ) ;
  195. if( l.isEmpty() ){
  196. auto ac = new QAction( tr( "List Is Empty" ),m_not_hidden_volume_menu ) ;
  197. ac->setEnabled( false ) ;
  198. m_not_hidden_volume_menu->addAction( ac ) ;
  199. }else{
  200. for( const auto& it : l ){
  201. auto ac = new QAction( it,m_not_hidden_volume_menu ) ;
  202. m_not_hidden_volume_menu->addAction( ac ) ;
  203. }
  204. }
  205. }
  206. void MainWindow::removeVolumeFromVisibleVolumeList( QAction * ac )
  207. {
  208. auto e = ac->text() ;
  209. e.remove( "&" ) ;
  210. auto table = m_ui->tableWidget ;
  211. zuluMountTask::addVolumeToHiddenVolumeList( e ) ;
  212. this->disableAll() ;
  213. tablewidget::selectRow( table,e ) ;
  214. utility::Task::suspendForOneSecond() ;
  215. tablewidget::deleteTableRow( table,e ) ;
  216. tablewidget::selectLastRow( table ) ;
  217. this->enableAll() ;
  218. }
  219. void MainWindow::favoriteClicked( QAction * ac )
  220. {
  221. auto e = ac->text() ;
  222. e.remove( "&" ) ;
  223. this->showMoungDialog( e ) ;
  224. }
  225. void MainWindow::showFavorites()
  226. {
  227. m_favorite_menu->clear() ;
  228. QStringList l = utility::readFavorites() ;
  229. if( l.isEmpty() ){
  230. auto ac = new QAction( tr( "List Is Empty" ),m_favorite_menu ) ;
  231. ac->setEnabled( false ) ;
  232. m_favorite_menu->addAction( ac ) ;
  233. }else{
  234. l.removeLast() ;
  235. for( const auto& it : l ){
  236. auto ac = new QAction( it.split( "\t" ).first(),m_favorite_menu ) ;
  237. m_favorite_menu->addAction( ac ) ;
  238. }
  239. }
  240. }
  241. void MainWindow::setLocalizationLanguage()
  242. {
  243. auto translator = new QTranslator( this ) ;
  244. const char * app = "zuluMount-gui" ;
  245. QByteArray r = utility::localizationLanguage( app ).toLatin1() ;
  246. if( r == "en_US" ){
  247. /*
  248. * english_US language,its the default and hence dont load anything
  249. */
  250. }else{
  251. translator->load( r.constData(),utility::localizationLanguagePath( app ) ) ;
  252. QCoreApplication::installTranslator( translator ) ;
  253. }
  254. }
  255. #define zuluMOUNT_AUTO_OPEN_FOLDER "/.zuluCrypt/zuluMount-gui.NoAutoOpenFolder"
  256. void MainWindow::autoOpenFolderOnMount( bool b )
  257. {
  258. QString x = utility::homePath() + zuluMOUNT_AUTO_OPEN_FOLDER ;
  259. m_autoOpenFolderOnMount = b ;
  260. if( b ){
  261. QFile::remove( x ) ;
  262. }else{
  263. QFile f( x ) ;
  264. f.open( QIODevice::WriteOnly ) ;
  265. f.close() ;
  266. }
  267. }
  268. bool MainWindow::autoOpenFolderOnMount( void )
  269. {
  270. QString x = utility::homePath() + zuluMOUNT_AUTO_OPEN_FOLDER ;
  271. return !QFile::exists( x ) ;
  272. }
  273. void MainWindow::startAutoMonitor()
  274. {
  275. m_mountInfo = new monitor_mountinfo( this,[ this ](){ this->quitApplication() ; } ) ;
  276. m_events = new events( this,m_mountInfo->stop() ) ;
  277. m_mountInfo->start() ;
  278. m_events->start() ;
  279. }
  280. void MainWindow::closeApplication()
  281. {
  282. m_events->stop() ;
  283. }
  284. /*
  285. * This should be the only function that closes the application
  286. */
  287. void MainWindow::pbMenu()
  288. {
  289. m_events->stop() ;
  290. }
  291. void MainWindow::quitApplication()
  292. {
  293. QCoreApplication::quit() ;
  294. }
  295. void MainWindow::autoMountVolume( volumeEntryProperties * e )
  296. {
  297. std::unique_ptr< volumeEntryProperties > entry( e ) ;
  298. if( entry && entry->entryisValid() ){
  299. QStringList l = entry->entryList() ;
  300. if( entry->encryptedVolume() ){
  301. this->addEntryToTable( true,l ) ;
  302. }else{
  303. if( m_autoMount ){
  304. mountPartition::instance( this,m_ui->tableWidget,[](){},[ this ]( const QString& e ){
  305. this->openMountPointPath( e ) ;
  306. } )->AutoMount( l ) ;
  307. }else{
  308. this->addEntryToTable( false,l ) ;
  309. }
  310. }
  311. }
  312. }
  313. void MainWindow::volumeRemoved( QString volume )
  314. {
  315. if( !volume.isEmpty() ){
  316. auto table = m_ui->tableWidget ;
  317. int row = tablewidget::columnHasEntry( table,volume ) ;
  318. if( row != -1 ){
  319. tablewidget::deleteRowFromTable( table,row ) ;
  320. /*
  321. * see if a user just removed the device without properly closing it/unmounting it
  322. * and try to do so for them
  323. */
  324. Task::exec( [ volume ](){ zuluMountTask::checkUnMount( volume ) ; } ) ;
  325. this->enableAll() ;
  326. }
  327. }
  328. }
  329. void MainWindow::removeVolume( QString volume )
  330. {
  331. if( volume.isEmpty() ){
  332. tablewidget::selectLastRow( m_ui->tableWidget ) ;
  333. this->enableAll() ;
  334. }else{
  335. tablewidget::deleteTableRow( m_ui->tableWidget,volume ) ;
  336. }
  337. }
  338. void MainWindow::itemEntered( QTableWidgetItem * item )
  339. {
  340. int row = item->row() ;
  341. auto table = item->tableWidget() ;
  342. QString m_point = table->item( row,1 )->text() ;
  343. QString x = table->item( row,3 )->text() ;
  344. QString z ;
  345. QString y ;
  346. if( m_point == "/" ){
  347. /*
  348. * we dont check if root path is publicly shared because the path it will produce (/run/media/public/)
  349. * will always return true,a solution is to examine /proc/self/mountinfo and thats work for another day
  350. */
  351. if( x == "Nil" ){
  352. x.clear() ;
  353. }
  354. z += tr( "LABEL=\"%1\"" ).arg( x ) ;
  355. }else if( m_point == "Nil" ){
  356. /*
  357. * volume is not mounted,cant know its LABEL value
  358. */
  359. x.clear() ;
  360. z += tr( "LABEL=\"%1\"" ).arg( x ) ;
  361. }else{
  362. if( x == "Nil" ){
  363. x.clear() ;
  364. }
  365. y = utility::shareMountPointToolTip( m_point ) ;
  366. if( y.isEmpty() ){
  367. z += tr( "LABEL=\"%1\"" ).arg( x ) ;
  368. }else{
  369. z += tr( "LABEL=\"%1\"\n%2" ).arg( x,y ) ;
  370. }
  371. }
  372. item->setToolTip( z ) ;
  373. }
  374. void MainWindow::startGUI()
  375. {
  376. if( !m_startHidden ){
  377. this->raiseWindow() ;
  378. }
  379. }
  380. void MainWindow::raiseWindow()
  381. {
  382. this->setVisible( true ) ;
  383. this->raise() ;
  384. this->show() ;
  385. this->setWindowState( Qt::WindowActive ) ;
  386. }
  387. void MainWindow::raiseWindow( QString volume )
  388. {
  389. this->setVisible( true ) ;
  390. this->raise() ;
  391. this->show() ;
  392. this->setWindowState( Qt::WindowActive ) ;
  393. this->showMoungDialog( volume ) ;
  394. }
  395. void MainWindow::Show()
  396. {
  397. QStringList l = QCoreApplication::arguments() ;
  398. m_startHidden = l.contains( "-e" ) ;
  399. m_folderOpener = utility::cmdArgumentValue( l,"-m","xdg-open" ) ;
  400. m_env = utility::cmdArgumentValue( l,"-z","" ) ;
  401. utility::setUID( utility::cmdArgumentValue( l,"-K","-1" ).toInt() ) ;
  402. QString volume = utility::cmdArgumentValue( l,"-d" ) ;
  403. new oneinstance( this,"zuluMount-gui.socket","startGUI",volume,[ this,volume ]( QObject * instance ){
  404. connect( instance,SIGNAL( raise() ),this,SLOT( raiseWindow() ) ) ;
  405. connect( instance,SIGNAL( raiseWithDevice( QString ) ),this,SLOT( raiseWindow( QString ) ) ) ;
  406. this->setUpApp( volume ) ;
  407. } ) ;
  408. }
  409. void MainWindow::showContextMenu( QTableWidgetItem * item,bool itemClicked )
  410. {
  411. QMenu m ;
  412. m.setFont( this->font() ) ;
  413. int row = item->row() ;
  414. QString mt = m_ui->tableWidget->item( row,1 )->text() ;
  415. QString device = m_ui->tableWidget->item( row,0 )->text() ;
  416. if( mt == "Nil" ){
  417. connect( m.addAction( tr( "Mount" ) ),SIGNAL( triggered() ),this,SLOT( slotMount() ) ) ;
  418. }else{
  419. QString mp = QString( "/run/media/private/%1/" ).arg( utility::userName() ) ;
  420. QString mp_1 = QString( "/home/%1/" ).arg( utility::userName() ) ;
  421. if( mt.startsWith( mp ) || mt.startsWith( mp_1 ) ){
  422. connect( m.addAction( tr( "Unmount" ) ),SIGNAL( triggered() ),this,SLOT( pbUmount() ) ) ;
  423. m.addSeparator() ;
  424. QString fs = m_ui->tableWidget->item( row,2 )->text() ;
  425. if( fs != "encfs" ){
  426. connect( m.addAction( tr( "Properties" ) ),SIGNAL( triggered() ),this,SLOT( volumeProperties() ) ) ;
  427. m.addSeparator() ;
  428. }
  429. m_sharedFolderPath = utility::sharedMountPointPath( mt ) ;
  430. if( m_sharedFolderPath.isEmpty() ){
  431. connect( m.addAction( tr( "Open Folder" ) ),SIGNAL( triggered() ),
  432. this,SLOT( slotOpenFolder() ) ) ;
  433. }else{
  434. connect( m.addAction( tr( "Open Private Folder" ) ),SIGNAL( triggered() ),
  435. this,SLOT( slotOpenFolder() ) ) ;
  436. connect( m.addAction( tr( "Open Shared Folder" ) ),SIGNAL( triggered() ),
  437. this,SLOT( slotOpenSharedFolder() ) ) ;
  438. }
  439. }else{
  440. m_sharedFolderPath = utility::sharedMountPointPath( mt ) ;
  441. if( m_sharedFolderPath.isEmpty() ){
  442. if( utility::pathIsReadable( mt ) ){
  443. connect( m.addAction( tr( "Properties" ) ),SIGNAL( triggered() ),this,SLOT( volumeProperties() ) ) ;
  444. m.addSeparator() ;
  445. connect( m.addAction( tr( "Open Folder" ) ),SIGNAL( triggered() ),
  446. this,SLOT( slotOpenFolder() ) ) ;
  447. }else{
  448. connect( m.addAction( tr( "Properties" ) ),SIGNAL( triggered() ),this,SLOT( volumeProperties() ) ) ;
  449. }
  450. }else{
  451. connect( m.addAction( tr( "Properties" ) ),SIGNAL( triggered() ),this,SLOT( volumeProperties() ) ) ;
  452. m.addSeparator() ;
  453. connect( m.addAction( tr( "Open Shared Folder" ) ),SIGNAL( triggered() ),
  454. this,SLOT( slotOpenSharedFolder() ) ) ;
  455. }
  456. }
  457. }
  458. m.addSeparator() ;
  459. m.addAction( tr( "Close Menu" ) ) ;
  460. if( itemClicked ){
  461. m.exec( QCursor::pos() ) ;
  462. }else{
  463. QPoint p = this->pos() ;
  464. int x = p.x() + 100 + m_ui->tableWidget->columnWidth( 0 ) ;
  465. int y = p.y() + 50 + m_ui->tableWidget->rowHeight( 0 ) * item->row() ;
  466. p.setX( x ) ;
  467. p.setY( y ) ;
  468. m.exec( p ) ;
  469. }
  470. }
  471. void MainWindow::itemClicked( QTableWidgetItem * item )
  472. {
  473. this->showContextMenu( item,true ) ;
  474. }
  475. void MainWindow::defaultButton()
  476. {
  477. int row = m_ui->tableWidget->currentRow() ;
  478. QString mt = m_ui->tableWidget->item( row,1 )->text() ;
  479. if( mt == "Nil" ){
  480. this->slotMount() ;
  481. }else{
  482. this->showContextMenu( m_ui->tableWidget->currentItem(),false ) ;
  483. }
  484. }
  485. void MainWindow::slotOpenSharedFolder()
  486. {
  487. this->openMountPoint( m_sharedFolderPath ) ;
  488. }
  489. void MainWindow::slotOpenFolder()
  490. {
  491. auto item = m_ui->tableWidget->currentItem() ;
  492. QString path = m_ui->tableWidget->item( item->row(),1 )->text() ;
  493. this->openMountPoint( path ) ;
  494. }
  495. void MainWindow::openMountPoint( const QString& m_point )
  496. {
  497. utility::openMountPoint( m_point,m_folderOpener,m_env ).then( [ this ]( bool failed ){
  498. if( failed ){
  499. QString x = tr( "Could not open mount point because \"%1\" tool does not appear to be working correctly").arg( m_folderOpener ) ;
  500. DialogMsg msg( this ) ;
  501. msg.ShowUIOK( tr( "Warning" ),x ) ;
  502. }
  503. } ) ;
  504. }
  505. void MainWindow::openMountPointPath( QString m )
  506. {
  507. if( m_autoOpenFolderOnMount ){
  508. this->openMountPoint( m ) ;
  509. }
  510. }
  511. void MainWindow::volumeProperties()
  512. {
  513. this->disableAll() ;
  514. QString volume = m_ui->tableWidget->item( m_ui->tableWidget->currentRow(),0 )->text() ;
  515. QString volumeType = m_ui->tableWidget->item( m_ui->tableWidget->currentRow(),2 )->text() ;
  516. QString r = zuluMountTask::volumeProperties( volume,volumeType ).await() ;
  517. DialogMsg msg( this ) ;
  518. if( r.isEmpty() ){
  519. msg.ShowUIOK( tr( "ERROR" ),
  520. tr( "Could not get volume properties.\nvolume is not open or was opened by a different user" ) ) ;
  521. }else{
  522. int i = r.indexOf( "\n" ) ;
  523. if( i != -1 ){
  524. msg.ShowUIVolumeProperties( tr( "Volume Properties" ),r.mid( i + 1 ) ) ;
  525. }else{
  526. msg.ShowUIOK( tr( "ERROR" ),
  527. tr( "Could not get volume properties.\nvolume is not open or was opened by a different user" ) ) ;
  528. }
  529. }
  530. this->enableAll() ;
  531. }
  532. void MainWindow::setUpShortCuts()
  533. {
  534. auto ac = new QAction( this ) ;
  535. QList<QKeySequence> keys ;
  536. keys.append( Qt::Key_Enter ) ;
  537. keys.append( Qt::Key_Return ) ;
  538. ac->setShortcuts( keys ) ;
  539. connect( ac,SIGNAL( triggered() ),this,SLOT( defaultButton() ) ) ;
  540. this->addAction( ac ) ;
  541. auto qa = new QAction( this ) ;
  542. QList<QKeySequence> z ;
  543. z.append( Qt::Key_M ) ;
  544. qa->setShortcuts( z ) ;
  545. connect( qa,SIGNAL( triggered() ),this,SLOT( pbMount() ) ) ;
  546. this->addAction( qa ) ;
  547. qa = new QAction( this ) ;
  548. QList<QKeySequence> p ;
  549. p.append( Qt::Key_U ) ;
  550. qa->setShortcuts( p ) ;
  551. connect( qa,SIGNAL( triggered() ),this,SLOT( pbUmount() ) ) ;
  552. this->addAction( qa ) ;
  553. qa = new QAction( this ) ;
  554. QList<QKeySequence> q ;
  555. q.append( Qt::Key_R ) ;
  556. qa->setShortcuts( q ) ;
  557. connect( qa,SIGNAL( triggered() ),this,SLOT( pbUpdate() ) ) ;
  558. this->addAction( qa ) ;
  559. qa = new QAction( this ) ;
  560. QList<QKeySequence> e ;
  561. e.append( Qt::Key_C ) ;
  562. qa->setShortcuts( e ) ;
  563. connect( qa,SIGNAL( triggered() ),this,SLOT( closeApplication() ) ) ;
  564. this->addAction( qa ) ;
  565. }
  566. void MainWindow::setUpFont()
  567. {
  568. this->setFont( utility::getFont( this ) ) ;
  569. }
  570. void MainWindow::closeEvent( QCloseEvent * e )
  571. {
  572. e->ignore() ;
  573. this->hide() ;
  574. }
  575. void MainWindow::slotTrayClicked( QSystemTrayIcon::ActivationReason e )
  576. {
  577. if( e == QSystemTrayIcon::Trigger ){
  578. if( this->isVisible() ){
  579. this->hide() ;
  580. }else{
  581. this->show() ;
  582. }
  583. }
  584. }
  585. void MainWindow::autoMountToggled( bool opt )
  586. {
  587. m_autoMount = opt ;
  588. }
  589. void MainWindow::dragEnterEvent( QDragEnterEvent * e )
  590. {
  591. e->accept() ;
  592. }
  593. void MainWindow::dropEvent( QDropEvent * e )
  594. {
  595. for( const auto& it : e->mimeData()->urls() ){
  596. this->showMoungDialog( it.path() ) ;
  597. }
  598. }
  599. void MainWindow::mount( const volumeEntryProperties& entry )
  600. {
  601. this->disableAll() ;
  602. if( entry.encryptedVolume() ){
  603. keyDialog::instance( this,m_ui->tableWidget,entry,[ this ](){
  604. this->enableAll() ;
  605. },[ this ]( const QString& e ){
  606. this->openMountPointPath( e ) ;
  607. } )->ShowUI() ;
  608. }else{
  609. mountPartition::instance( this,m_ui->tableWidget,[ this ](){
  610. this->enableAll() ;
  611. },[ this ]( const QString& e ){
  612. this->openMountPointPath( e ) ;
  613. } )->ShowUI( entry ) ;
  614. }
  615. }
  616. void MainWindow::slotMount()
  617. {
  618. auto table = m_ui->tableWidget ;
  619. int row = table->currentRow() ;
  620. this->mount( volumeEntryProperties( tablewidget::tableRowEntries( table,row ) ) ) ;
  621. }
  622. void MainWindow::showMoungDialog( const volumeEntryProperties& v )
  623. {
  624. if( v.isEmpty() ){
  625. DialogMsg msg( this ) ;
  626. msg.ShowUIOK( tr( "ERROR" ),
  627. tr( "Permission to access the volume was denied\nor\nthe volume is not supported\n(LVM/MDRAID signatures found)" ) ) ;
  628. this->enableAll() ;
  629. }else{
  630. this->mount( v ) ;
  631. }
  632. }
  633. void MainWindow::showMoungDialog( const QString& volume )
  634. {
  635. if( !volume.isEmpty() ){
  636. if( utility::pathPointsToAFile( volume ) ){
  637. this->showMoungDialog( zuluMountTask::getVolumeProperties( volume ).await() ) ;
  638. }else if( utility::pathPointsToAFolder( volume ) ){
  639. this->mount( volumeEntryProperties( { volume,"Nil","encfs","Nil","Nil","Nil" } ) ) ;
  640. }
  641. }
  642. }
  643. void MainWindow::pbMount()
  644. {
  645. this->disableAll() ;
  646. QString path = QFileDialog::getOpenFileName( this,tr( "Select An Image File To Mount" ),utility::homePath() ) ;
  647. if( path.isEmpty() ){
  648. this->enableAll() ;
  649. }else{
  650. this->showMoungDialog( path ) ;
  651. }
  652. }
  653. void MainWindow::unlockencfs()
  654. {
  655. this->disableAll() ;
  656. QString path = QFileDialog::getExistingDirectory( this,tr( "Select An Encfs Volume Directory" ),utility::homePath(),QFileDialog::ShowDirsOnly ) ;
  657. if( path.isEmpty() ){
  658. this->enableAll() ;
  659. }else{
  660. this->showMoungDialog( path ) ;
  661. }
  662. }
  663. QFont MainWindow::getSystemVolumeFont()
  664. {
  665. QFont f = this->font() ;
  666. f.setItalic( !f.italic() ) ;
  667. f.setBold( !f.bold() ) ;
  668. return f ;
  669. }
  670. void MainWindow::addEntryToTable( bool systemVolume,const QStringList& l )
  671. {
  672. if( systemVolume ){
  673. tablewidget::addRowToTable( m_ui->tableWidget,l,this->getSystemVolumeFont() ) ;
  674. }else{
  675. tablewidget::addRowToTable( m_ui->tableWidget,l ) ;
  676. }
  677. }
  678. void MainWindow::removeEntryFromTable( QString volume )
  679. {
  680. auto table = m_ui->tableWidget ;
  681. int r = tablewidget::columnHasEntry( table,volume ) ;
  682. if( r != -1 ){
  683. tablewidget::deleteRowFromTable( table,r ) ;
  684. this->enableAll() ;
  685. }else{
  686. this->pbUpdate() ;
  687. }
  688. }
  689. void MainWindow::volumeMiniProperties( bool valid,volumeEntryProperties * e )
  690. {
  691. std::unique_ptr< volumeEntryProperties > volumeInfo( e ) ;
  692. this->disableAll() ;
  693. if( valid ){
  694. this->updateList( *volumeInfo ) ;
  695. this->enableAll() ;
  696. }else{
  697. this->pbUpdate() ;
  698. }
  699. }
  700. void MainWindow::volumeMiniProperties( volumeEntryProperties * volumeInfo )
  701. {
  702. this->volumeMiniProperties( volumeInfo,volumeInfo ) ;
  703. }
  704. void MainWindow::volumeMiniProperties_0( volumeEntryProperties * volumeInfo )
  705. {
  706. this->volumeMiniProperties( volumeInfo && volumeInfo->mounted(),volumeInfo ) ;
  707. }
  708. void MainWindow::updateList( const volumeEntryProperties& entry )
  709. {
  710. if( entry.isNotEmpty() ){
  711. auto table = m_ui->tableWidget ;
  712. int row = tablewidget::columnHasEntry( table,entry.volumeName() ) ;
  713. if( row == -1 ){
  714. row = tablewidget::addEmptyRow( table ) ;
  715. }
  716. if( entry.isSystem() ){
  717. tablewidget::updateRowInTable( table,entry.entryList(),row,this->getSystemVolumeFont() ) ;
  718. }else{
  719. tablewidget::updateRowInTable( table,entry.entryList(),row,this->font() ) ;
  720. }
  721. tablewidget::selectRow( table,row ) ;
  722. }
  723. }
  724. void MainWindow::pbUmount()
  725. {
  726. this->disableAll() ;
  727. int row = m_ui->tableWidget->currentRow() ;
  728. QString path = m_ui->tableWidget->item( row,0 )->text() ;
  729. QString type = m_ui->tableWidget->item( row,2 )->text() ;
  730. if( type == "encfs" ){
  731. QString m = m_ui->tableWidget->item( row,1 )->text() ;
  732. if( !zuluMountTask::encfsUnmount( m ).await() ){
  733. DialogMsg m( this ) ;
  734. m.ShowUIOK( tr( "ERROR" ),tr( "Failed to unmount encfs volume" ) ) ;
  735. this->enableAll() ;
  736. }
  737. }else{
  738. auto r = zuluMountTask::unmountVolume( path,type ).await() ;
  739. if( r.failed() ){
  740. DialogMsg m( this ) ;
  741. m.ShowUIOK( tr( "ERROR" ),r.output() ) ;
  742. this->enableAll() ;
  743. }
  744. }
  745. }
  746. void MainWindow::unMountAll()
  747. {
  748. this->disableAll() ;
  749. auto table = m_ui->tableWidget ;
  750. QStringList x = tablewidget::tableColumnEntries( table,1 ) ;
  751. QStringList y = tablewidget::tableColumnEntries( table,0 ) ;
  752. QStringList z = tablewidget::tableColumnEntries( table,2 ) ;
  753. QStringList p ;
  754. QStringList q ;
  755. QStringList n ;
  756. QString a = utility::userName() ;
  757. QString b = utility::mountPath( QString() ) ;
  758. QString c = utility::homeMountPath( QString() ) ;
  759. int k = x.size() ;
  760. for( int i = 0 ; i < k ; i++ ){
  761. const QString& e = x.at( i ) ;
  762. if( e.startsWith( b ) || e.startsWith( c ) ){
  763. p.append( y.at( i ) ) ;
  764. q.append( z.at( i ) ) ;
  765. n.append( e ) ;
  766. }
  767. }
  768. m_removeAllVolumes = true ;
  769. Task::await( [ & ](){
  770. if( p.isEmpty() ){
  771. utility::Task::waitForOneSecond() ;
  772. }else{
  773. for( int i = p.size() - 1 ; i >= 0 ; i-- ){
  774. const QString& e = q.at( i ) ;
  775. if( e == "encfs" ){
  776. zuluMountTask::encfsUnmount( n.at( i ) ).get() ;
  777. }else{
  778. zuluMountTask::volumeUnmount( p.at( i ),e ) ;
  779. }
  780. utility::Task::waitForOneSecond() ;
  781. }
  782. utility::Task::waitForTwoSeconds() ;
  783. }
  784. } ) ;
  785. this->enableAll_1() ;
  786. }
  787. void MainWindow::pbUpdate()
  788. {
  789. this->disableAll() ;
  790. auto r = zuluMountTask::updateVolumeList().await() ;
  791. this->updateVolumeList( r ) ;
  792. this->removeDisappearedEntries( r ) ;
  793. }
  794. void MainWindow::updateVolumeList( const QVector< volumeEntryProperties >& r )
  795. {
  796. if( r.isEmpty() ){
  797. DialogMsg msg( this ) ;
  798. msg.ShowUIOK( tr( "ERROR" ),
  799. tr( "Reading partition properties took longer than expected and operation was terminated,click refresh to try again" ) ) ;
  800. this->enableAll() ;
  801. }else{
  802. for( const auto& it : r ){
  803. if( it.entryisValid() ){
  804. this->updateList( it ) ;
  805. }
  806. }
  807. }
  808. }
  809. void MainWindow::removeDisappearedEntries( const QVector< volumeEntryProperties >& entries )
  810. {
  811. /*
  812. * Below routine removes an entries from the table if they are found not to be
  813. * present on the the list of volumes we just received.This is necessary
  814. * for example to remove no longer valid options like a removed cdrom
  815. */
  816. if( entries.isEmpty() ){
  817. return this->enableAll() ;
  818. }
  819. auto table = m_ui->tableWidget ;
  820. QStringList l = tablewidget::tableColumnEntries( table,0 ) ;
  821. auto _hasNoEntry = [&]( const QString& volume ){
  822. for( const auto& it : entries ){
  823. if( it.volumeName() == volume ){
  824. if( it.fileSystem() == "encfs" ){
  825. return false ;
  826. }
  827. if( it.volumeSize() == "Nil" ){
  828. return true ;
  829. }else{
  830. return false ;
  831. }
  832. }
  833. }
  834. return true ;
  835. } ;
  836. QStringList z ;
  837. for( const auto& it : l ){
  838. if( _hasNoEntry( it ) ){
  839. z.append( it ) ;
  840. }
  841. }
  842. auto _done = [ this ](){
  843. tablewidget::selectLastRow( m_ui->tableWidget ) ;
  844. this->enableAll() ;
  845. } ;
  846. if( z.isEmpty() ){
  847. _done() ;
  848. }else{
  849. for( const auto& e : z ){
  850. tablewidget::selectRow( table,e ) ;
  851. utility::Task::suspendForOneSecond() ;
  852. tablewidget::deleteTableRow( table,e ) ;
  853. }
  854. utility::Task::suspendForOneSecond() ;
  855. _done() ;
  856. }
  857. }
  858. void MainWindow::slotCurrentItemChanged( QTableWidgetItem * current,QTableWidgetItem * previous )
  859. {
  860. tablewidget::selectTableRow( current,previous ) ;
  861. }
  862. void MainWindow::disableAll()
  863. {
  864. m_ui->pbmenu->setEnabled( false ) ;
  865. m_ui->pbmount->setEnabled( false ) ;
  866. m_ui->pbupdate->setEnabled( false ) ;
  867. m_ui->tableWidget->setEnabled( false ) ;
  868. m_ui->pbunlockencfs->setEnabled( false ) ;
  869. }
  870. void MainWindow::enableAll()
  871. {
  872. if( m_removeAllVolumes ){
  873. return ;
  874. }
  875. m_ui->pbmenu->setEnabled( true ) ;
  876. m_ui->pbupdate->setEnabled( true ) ;
  877. m_ui->tableWidget->setEnabled( true ) ;
  878. m_ui->pbmount->setEnabled( true ) ;
  879. m_ui->tableWidget->setFocus() ;
  880. m_ui->pbunlockencfs->setEnabled( true ) ;
  881. if( utility::runningInMixedMode() ){
  882. /*
  883. * FUSE related permission issues prevents us from currently supporting
  884. * unlocking encfs volumes when running in mixed mode.
  885. */
  886. m_ui->pbunlockencfs->setEnabled( false ) ;
  887. }
  888. }
  889. void MainWindow::enableAll_1()
  890. {
  891. m_removeAllVolumes = false ;
  892. this->enableAll() ;
  893. }
  894. #define zuluMOUNT_AUTOPATH "/.zuluCrypt/zuluMount-gui.autoMountPartitions"
  895. bool MainWindow::autoMount()
  896. {
  897. QFile f( utility::homePath() + zuluMOUNT_AUTOPATH ) ;
  898. return f.exists() ;
  899. }
  900. MainWindow::~MainWindow()
  901. {
  902. QFile f( utility::homePath() + zuluMOUNT_AUTOPATH ) ;
  903. if( m_autoMountAction ){
  904. if( m_autoMountAction->isChecked() ){
  905. if( !f.exists() ){
  906. f.open( QIODevice::WriteOnly ) ;
  907. f.close() ;
  908. }
  909. }else{
  910. f.remove() ;
  911. }
  912. }
  913. QVector<int> e ;
  914. auto q = m_ui->tableWidget ;
  915. const QRect& r = this->window()->geometry() ;
  916. e << r.x()
  917. << r.y()
  918. << r.width()
  919. << r.height()
  920. << q->columnWidth( 0 )
  921. << q->columnWidth( 1 )
  922. << q->columnWidth( 2 )
  923. << q->columnWidth( 4 )
  924. << q->columnWidth( 5 ) ;
  925. utility::setWindowDimensions( e,"zuluMount" ) ;
  926. }