/src/Application.cpp

https://github.com/jingoro/browseurl · C++ · 263 lines · 228 code · 28 blank · 7 comment · 19 complexity · 0ac97451b0ae381d45392a861af61334 MD5 · raw file

  1. #include <QClipboard>
  2. #include <QDir>
  3. #include <QFile>
  4. #include <QFileOpenEvent>
  5. #include <QMessageBox>
  6. #include <QProcess>
  7. #include <QSettings>
  8. #include <QStringList>
  9. #include <QUrl>
  10. #include "Application.h"
  11. #if defined( Q_WS_MAC )
  12. #include "MacProxy.h"
  13. #elif defined( Q_OS_WIN )
  14. #error TODO Unsupported platform!
  15. #elif defined( Q_OS_UNIX )
  16. #error TODO Unsupported platform!
  17. #else
  18. #error Unsupported platform!
  19. #endif
  20. Application::Application( int &argc, char **argv ) :
  21. QApplication( argc, argv ),
  22. osProxy( createOsProxy() ),
  23. domainModel( new DomainModel() ),
  24. aboutDialog( 0 ),
  25. preferencesDialog( 0 ),
  26. openUrlTime( QTime() ),
  27. openUrlCount( 0 )
  28. {
  29. setApplicationName( BROWSEURL_APPLICATION );
  30. setOrganizationName( BROWSEURL_ORG_NAME );
  31. setOrganizationDomain( BROWSEURL_ORG_DOMAIN );
  32. readSettings();
  33. setQuitOnLastWindowClosed( false );
  34. createTrayMenu();
  35. connect( this, SIGNAL( aboutToQuit() ), this, SLOT( updateSettings() ) );
  36. connect( osProxy, SIGNAL( filesForCopyLinks( const QStringList & ) ),
  37. this, SLOT( copyLinksFromFiles( const QStringList & ) ) );
  38. }
  39. Application::~Application()
  40. {
  41. delete preferencesDialog;
  42. delete aboutDialog;
  43. delete domainModel;
  44. delete osProxy;
  45. }
  46. OsProxy * Application::createOsProxy()
  47. {
  48. #if defined( Q_OS_MAC )
  49. return new MacProxy( this );
  50. #elif defined( Q_OS_WIN )
  51. return new WinProxy( this ); // TODO
  52. #elif defined( Q_OS_UNIX )
  53. return new UnixProxy( this ); // TODO
  54. #else
  55. #error Unsupported platform!
  56. #endif
  57. }
  58. void Application::createTrayMenu()
  59. {
  60. trayMenu = new TrayMenu( 0 );
  61. trayIcon = new QSystemTrayIcon( 0 );
  62. trayIcon->setContextMenu( trayMenu );
  63. trayIcon->setIcon( QIcon( ":/heart.svg" ) );
  64. trayIcon->show();
  65. }
  66. void Application::showAboutDialog()
  67. {
  68. if ( ! aboutDialog ) {
  69. aboutDialog = new AboutDialog();
  70. }
  71. aboutDialog->show();
  72. }
  73. void Application::showPreferencesDialog()
  74. {
  75. if ( ! preferencesDialog ) {
  76. preferencesDialog = new PreferencesDialog( osProxy, domainModel );
  77. connect( preferencesDialog, SIGNAL( rejected() ), this, SLOT( updateSettings() ) );
  78. }
  79. preferencesDialog->show();
  80. }
  81. bool Application::event( QEvent *event )
  82. {
  83. if ( event->type() == QEvent::FileOpen ) {
  84. QUrl url = static_cast<QFileOpenEvent *>( event )->url();
  85. if ( ! url.isEmpty() ) {
  86. // if ( url.scheme() == QString( "file" ) ) {
  87. // copyLink( url.path() );
  88. // return true;
  89. // } else
  90. if ( url.scheme() == QString( BROWSEURL_SCHEME ) ) {
  91. openUrl( url );
  92. return true;
  93. }
  94. }
  95. }
  96. return QApplication::event( event );
  97. }
  98. void Application::openUrl( const QUrl &url )
  99. {
  100. if ( openUrlThrottle() ) {
  101. qDebug("Throttling...");
  102. return;
  103. }
  104. QString domain;
  105. QString domainPath;
  106. if ( ! getDomainFromUrl( url, &domain, &domainPath ) ) {
  107. showError( tr("No matching domains for URL %1" ).
  108. arg( url.toString() ) );
  109. return;
  110. }
  111. QString requestPath = QDir::cleanPath(domainPath + url.path());
  112. if ( ! requestPath.startsWith(domainPath) ) {
  113. showError( tr("Invalid request path %1 for URL %2" ).
  114. arg( requestPath ).arg( url.toString() ) );
  115. return;
  116. }
  117. if ( ! QFile(requestPath).exists() ) {
  118. showError( tr("Path %1 does not exist for URL %2" ).
  119. arg( requestPath ).arg( url.toString() ) );
  120. return;
  121. }
  122. openPathInExplorer( requestPath );
  123. }
  124. bool Application::openUrlThrottle()
  125. {
  126. if ( openUrlTime.isNull() ||
  127. openUrlTime.elapsed() > BROWSEURL_THROTTLE_TIMEOUT ) {
  128. openUrlCount = 1;
  129. openUrlTime = QTime();
  130. openUrlTime.start();
  131. return false;
  132. } else {
  133. openUrlCount ++;
  134. return ( openUrlCount > BROWSEURL_THROTTLE_COUNT );
  135. }
  136. }
  137. bool Application::getDomainFromUrl( const QUrl &url,
  138. QString *aDomain, QString *domainPath )
  139. {
  140. // TODO
  141. QString testDomain = url.host();
  142. QList < Domain > domains = domainModel->getDomains();
  143. foreach ( const Domain &domain, domains ) {
  144. if ( testDomain == domain.getDomain() ) {
  145. *aDomain = domain.getDomain();
  146. *domainPath = domain.getLocalPath();
  147. return true;
  148. }
  149. }
  150. return false;
  151. }
  152. void Application::openPathInExplorer( const QString & path )
  153. {
  154. osProxy->browsePath( path );
  155. }
  156. void Application::showError( const QString &message )
  157. {
  158. QMessageBox::critical( 0, tr( "BrowseURL Error" ), message );
  159. }
  160. void Application::copyLinksFromFiles( const QStringList & files )
  161. {
  162. QStringList copyLinks;
  163. foreach ( const QString & file, files ) {
  164. QString copyLink = createCopyLink( file );
  165. if ( copyLink.isEmpty() ) {
  166. showError( tr( "No matching BrowseURL domain for local path %1" ).
  167. arg( file ) );
  168. return;
  169. }
  170. copyLinks.append( copyLink );
  171. }
  172. QApplication::clipboard()->setText( copyLinks.join( "\n" ) );
  173. }
  174. QString Application::createCopyLink( const QString & path ) const
  175. {
  176. QList < Domain > domains = domainModel->getDomains();
  177. foreach ( const Domain & domain, domains ) {
  178. if ( path.startsWith( domain.getLocalPath() ) ) {
  179. QUrl url;
  180. url.setScheme( QString( BROWSEURL_SCHEME ) );
  181. url.setHost( domain.getDomain() );
  182. url.setPath( path.mid( domain.getLocalPath().length() ) );
  183. return QString( url.toEncoded() );
  184. }
  185. }
  186. return QString();
  187. }
  188. void Application::readSettings()
  189. {
  190. QSettings settings;
  191. if ( ! settings.value( "domains/size" ).isValid() ) {
  192. setDefaultSettings();
  193. return;
  194. }
  195. QList < Domain > domains = domainModel->getDomains();
  196. int size = settings.beginReadArray("domains");
  197. for ( int i = 0; i < size; i++ ) {
  198. settings.setArrayIndex( i );
  199. QString domain = settings.value( "domain" ).toString();
  200. QString localPath = settings.value( "localPath" ).toString();
  201. domainModel->addDomain( domain, localPath );
  202. }
  203. settings.endArray();
  204. }
  205. void Application::setDefaultSettings()
  206. {
  207. qDebug( "setDefaultSettings()" );
  208. domainModel->addDomain( "dropbox", QDir::homePath() + "/Dropbox" );
  209. domainModel->addDomain( "aerofs", QDir::homePath() + "/AeroFS" );
  210. domainModel->addDomain( "home", QDir::homePath() );
  211. osProxy->enableAutostart();
  212. #if defined( Q_WS_MAC )
  213. // TODO
  214. QProcess::execute( QString( "/System/Library/CoreServices/pbs" ) );
  215. #endif
  216. }
  217. void Application::writeSettings()
  218. {
  219. QSettings settings;
  220. QList < Domain > domains = domainModel->getDomains();
  221. int i = 0;
  222. settings.beginWriteArray("domains");
  223. foreach ( const Domain &domain, domains ) {
  224. settings.setArrayIndex( i );
  225. settings.setValue( "domain", domain.getDomain() );
  226. settings.setValue( "localPath", domain.getLocalPath() );
  227. i++;
  228. }
  229. settings.endArray();
  230. }
  231. void Application::updateSettings()
  232. {
  233. //qDebug("updateSettings");
  234. writeSettings();
  235. }