Exemple #1
0
K3bDataItem* K3bDirItem::takeDataItem( K3bDataItem* item )
{
  int x = m_children.findRef( item );
  if( x > -1 ) {
    K3bDataItem* item = m_children.take();
    updateSize( item, true );
    if( item->isDir() )
      updateFiles( -1*((K3bDirItem*)item)->numFiles(), -1*((K3bDirItem*)item)->numDirs()-1 );
    else
      updateFiles( -1, 0 );

    item->m_parentDir = 0;

    // inform the doc
    if( doc() )
      doc()->itemRemovedFromDir( this, item );

    if( item->isFile() ) {
      // restore the item imported from an old session
      if( static_cast<K3bFileItem*>(item)->replaceItemFromOldSession() )
	addDataItem( static_cast<K3bFileItem*>(item)->replaceItemFromOldSession() );
    }

    return item;
  }
  else
    return 0;
}
Exemple #2
0
K3bDirItem* K3bDirItem::addDataItem( K3bDataItem* item )
{
  // check if we are a subdir of item
  if( K3bDirItem* dirItem = dynamic_cast<K3bDirItem*>(item) ) {
    if( dirItem->isSubItem( this ) ) {
      kdDebug() << "(K3bDirItem) trying to move a dir item down in it's own tree." << endl;
      return this;
    }
  }

  if( m_children.findRef( item ) == -1 ) {
    if( item->isFile() ) {
      // do we replace an old item?
      QString name = item->k3bName();
      int cnt = 1;
      while( K3bDataItem* oldItem = find( name ) ) {
	if( !oldItem->isDir() && oldItem->isFromOldSession() ) {
	  // in this case we remove this item from it's parent and save it in the new one
	  // to be able to recover it
	  oldItem->take();
	  static_cast<K3bSessionImportItem*>(oldItem)->setReplaceItem( static_cast<K3bFileItem*>(item) );
	  static_cast<K3bFileItem*>(item)->setReplacedItemFromOldSession( oldItem );
	  break;
	}
	else {
	  //
	  // add a counter to the filename
	  //
	  if( item->k3bName()[item->k3bName().length()-4] == '.' )
	    name = item->k3bName().left( item->k3bName().length()-4 ) + QString::number(cnt++) + item->k3bName().right(4);
	  else
	    name = item->k3bName() + QString::number(cnt++);
	}
      }
      item->setK3bName( name );
    }

    m_children.append( item->take() );
    updateSize( item, false );
    if( item->isDir() )
      updateFiles( ((K3bDirItem*)item)->numFiles(), ((K3bDirItem*)item)->numDirs()+1 );
    else
      updateFiles( 1, 0 );

    item->m_parentDir = this;

    // inform the doc
    if( doc() )
      doc()->itemAddedToDir( this, item );
  }

  return this;
}
Exemple #3
0
LDeskBarPlugin::LDeskBarPlugin(QWidget *parent, QString id, bool horizontal) : LPPlugin(parent, id, horizontal){
  this->layout()->setContentsMargins(0,0,0,0);
  this->setStyleSheet( "QToolButton::menu-indicator{ image: none; } QToolButton{ padding: 0px; }");

  //initialize the desktop bar items
  initializeDesktop();
  //setup the directory watcher
  QString fav = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/favorites.list";
  if(!QFile::exists(fav)){ QProcess::execute("touch \""+fav+"\""); }
  watcher = new QFileSystemWatcher(this);
    watcher->addPath( fav );
  connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(filechanged(QString)) );
  QTimer::singleShot(1,this, SLOT(updateFiles()) ); //make sure to load it the first time
  QTimer::singleShot(0,this, SLOT(OrientationChange()) ); //adjust sizes/layout
  connect(QApplication::instance(), SIGNAL(DesktopFilesChanged()), this, SLOT(updateFiles()) );
}
Exemple #4
0
MusicModel::MusicModel(QString const & token, QString const & user, QObject *parent) :
    QAbstractListModel(parent)
{
    connect(&networkManager, SIGNAL(finished(QNetworkReply*)), SLOT(parseReply(QNetworkReply*)));
    this -> token = token;
    this -> user = user;

    player.setNotifyInterval(1000);
    connect(&player, SIGNAL(positionChanged(qint64)), SLOT(positionchanged(qint64)));
    connect(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), SLOT(statechangde(QMediaPlayer::MediaStatus)));
    updateFiles();}
void UniboardSankoreTransition::documentTransition()
{
    if (QFileInfo(mUniboardSourceDirectory).exists() || QFileInfo(mOldSankoreDirectory).exists()){
        QString uniboardDocumentDirectory = mUniboardSourceDirectory + "/document";

        QFileInfoList fileInfoList = UBFileSystemUtils::allElementsInDirectory(uniboardDocumentDirectory);
        fileInfoList << UBFileSystemUtils::allElementsInDirectory(mOldSankoreDirectory + "/document");

        QString backupDirectoryPath = UBFileSystemUtils::normalizeFilePath(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation));

        if (fileInfoList.count() != 0){
            mTransitionDlg = new UBUpdateDlg(NULL, fileInfoList.count(), backupDirectoryPath);
            connect(mTransitionDlg, SIGNAL(updateFiles()), this, SLOT(startDocumentTransition()));
            connect(this, SIGNAL(transitionFinished(bool)), mTransitionDlg, SLOT(onFilesUpdated(bool)));
            mTransitionDlg->show();
        }
Exemple #6
0
void FClient::updateAll()
{
	/* request that the file and directory lists be rebuilt */
	printf("updating file list\n");
	requestFileListRebuild();

	/* get local copies of the file and directory lists */
	printf("filelist.txt\n");
	updateFile("filelist.txt");
	printf("dirlist.txt\n");
	updateFile("dirlist.txt");

	/* process each of these files */
	printf("update directory structure\n");
	updateDirectoryStructure("dirlist.txt");

	/* update the files */
	printf("updating the files\n");
	updateFiles("filelist.txt");
}
void QFSEventsFileSystemWatcherEngine::run()
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
    threadsRunLoop = CFRunLoopGetCurrent();
    FSEventStreamScheduleWithRunLoop(fsStream, threadsRunLoop, kCFRunLoopDefaultMode);
    bool startedOK = FSEventStreamStart(fsStream);
    // It's recommended by Apple that you only update the files after you've started
    // the stream, because otherwise you might miss an update in between starting it.
    updateFiles();
#ifdef QT_NO_DEBUG
    Q_UNUSED(startedOK);
#else
    Q_ASSERT(startedOK);
#endif
    // If for some reason we called stop up above (and invalidated our stream), this call will return
    // immediately.
    CFRunLoopRun();
    threadsRunLoop = 0;
    QMutexLocker locker(&mutex);
    waitForStop.wakeAll();
#endif
}
void FileSystemWatcher::notifyReadyRead()
{
    FSUserData data;
    {
        enum { MaxEvents = 5 };
        struct kevent events[MaxEvents];
        struct timespec nullts = { 0, 0 };
        int ret;
        for (;;) {
            ret = ::kevent(mFd, 0, 0, events, MaxEvents, &nullts);
            if (ret == 0) {
                break;
            } else if (ret == -1) {
                error("FileSystemWatcher::notifyReadyRead() kevent failed (%d) %s",
                      errno, Rct::strerror().constData());
                break;
            }
            assert(ret > 0 && ret <= MaxEvents);
            for (int i = 0; i < ret; ++i) {
                std::unique_lock<std::mutex> lock(mMutex);
                const struct kevent& event = events[i];
                const Path p = mWatchedById.value(event.ident);
                if (event.flags & EV_ERROR) {
                    error("FileSystemWatcher::notifyReadyRead() kevent element failed for '%s' (%ld) %s",
                          p.constData(), event.data, Rct::strerror(event.data).constData());
                    continue;
                }
                if (p.isEmpty()) {
                    warning() << "FileSystemWatcher::notifyReadyRead() We don't seem to be watching " << p;
                    continue;
                }
                if (event.fflags & (NOTE_DELETE|NOTE_REVOKE|NOTE_RENAME)) {
                    // our path has been removed
                    const int wd = event.ident;
                    mWatchedById.remove(wd);
                    mWatchedByPath.remove(p);

                    data.all.clear();
                    Map<Path, uint64_t>::iterator it = mTimes.lower_bound(p);
                    while (it != mTimes.end() && it->first.startsWith(p)) {
                        data.all.insert(it->first);
                        mTimes.erase(it++);
                    }

                    struct kevent change;
                    struct timespec nullts = { 0, 0 };
                    EV_SET(&change, wd, EVFILT_VNODE, EV_DELETE, 0, 0, 0);
                    ::kevent(mFd, &change, 1, 0, 0, &nullts);
                    ::close(wd);
                } else if (p.exists()) {
                    // Figure out what has been changed
                    data.watcher = this;
                    data.added.clear();
                    data.modified.clear();
                    data.all.clear();
                    Map<Path, uint64_t>::iterator it = mTimes.lower_bound(p);
                    while (it != mTimes.end() && it->first.startsWith(p)) {
                        data.all.insert(it->first);
                        ++it;
                    }
                    //printf("before updateFiles, path %s, all %d\n", p.nullTerminated(), data.all.size());
                    p.visit([&data](const Path &p) {
                            return updateFiles(p, &data);
                            });
                    //printf("after updateFiles, added %d, modified %d, removed %d\n",
                    //       data.added.size(), data.modified.size(), data.all.size());

                    lock.unlock();
                    struct {
                        Signal<std::function<void(const Path&)> > &signal;
                        const Set<Path> &paths;
                    } signals[] = {
                        { mModified, data.modified },
                        { mAdded, data.added }
                    };
                    const unsigned int count = sizeof(signals) / sizeof(signals[0]);
                    for (unsigned i=0; i<count; ++i) {
                        for (Set<Path>::const_iterator it = signals[i].paths.begin(); it != signals[i].paths.end(); ++it) {
                            signals[i].signal(*it);
                        }
                    }
                }

                if (lock.owns_lock())
                    lock.unlock();
                for (Set<Path>::const_iterator it = data.all.begin(); it != data.all.end(); ++it) {
                    mRemoved(*it);
                }
            }
        }
    }
}
Exemple #9
0
void LDeskBarPlugin::filechanged(QString file){
  updateFiles();
  if(!watcher->files().contains(file)){ watcher->addPath(file); } //make sure the file does not get removed from the watcher
}
Exemple #10
0
int main(int argc, char *argv[])
{ 
#ifdef WINDOWS_SYS
	{
		/* Set the current directory to the application dir,
		   because the start dir with autostart from the registry run key is not the exe dir */
		QApplication app(argc, argv);
		QDir::setCurrent(QCoreApplication::applicationDirPath());
	}
#endif

	QStringList args = char_array_to_stringlist(argv+1, argc-1);

	Q_INIT_RESOURCE(images);

	rsiface = NULL;

	NotifyQt *notify = NotifyQt::Create();
	createRsIface(*notify);
	createRsControl(*rsiface, *notify);

	/* RetroShare Core Objects */
	RsInit::InitRsConfig();
	int initResult = RsInit::InitRetroShare(argc, argv);

	if(initResult == RS_INIT_NO_KEYRING)	// happens when we already have accounts, but no pgp key. This is when switching to the openpgp-sdk version.
	{
		QApplication dummyApp (argc, argv); // needed for QMessageBox
		/* Translate into the desired language */
		LanguageSupport::translate(LanguageSupport::defaultLanguageCode());

		QMessageBox msgBox;
		msgBox.setText(QObject::tr("This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although GPG keys are mentionned by existing RetroShare accounts, probably because you just changed to this new version of the software."));
		msgBox.setInformativeText(QObject::tr("Choose between:<br><ul><li><b>Ok</b> to copy the existing keyring from gnupg (safest bet), or </li><li><b>Close without saving</b> to start fresh with an empty keyring (you will be asked to create a new PGP key to work with RetroShare, or import a previously saved pgp keypair). </li><li><b>Cancel</b> to quit and forge a keyring by yourself (needs some PGP skills)</li></ul>"));
		msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Discard | QMessageBox::Cancel);
		msgBox.setDefaultButton(QMessageBox::Ok);
		msgBox.setWindowIcon(QIcon(":/images/rstray3.png"));

		int ret = msgBox.exec();

		if(ret == QMessageBox::Cancel)
			return 0 ;
		if(ret == QMessageBox::Ok)
		{
			if(!RsInit::copyGnuPGKeyrings())
				return 0 ; 

			initResult = RsInit::InitRetroShare(argc, argv);

			displayWarningAboutDSAKeys() ;

		}
		else
			initResult = RS_INIT_OK ;
	}

	if (initResult < 0) {
		/* Error occured */
		QApplication dummyApp (argc, argv); // needed for QMessageBox
		/* Translate into the desired language */
		LanguageSupport::translate(LanguageSupport::defaultLanguageCode());

		displayWarningAboutDSAKeys();

		QMessageBox mb(QMessageBox::Critical, QObject::tr("RetroShare"), "", QMessageBox::Ok);
		mb.setWindowIcon(QIcon(":/images/rstray3.png"));

		switch (initResult) 
		{
			case RS_INIT_AUTH_FAILED:
				std::cerr << "RsInit::InitRetroShare AuthGPG::InitAuth failed" << std::endl;
				mb.setText(QObject::tr("Inititialize failed. Wrong or missing installation of gpg."));
				break;
			default:
				/* Unexpected return code */
				std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl;
				mb.setText(QObject::tr("An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult));
				break;
		}
		mb.exec();
		return 1;
	}

	/* create global settings object
	   path maybe wrong, when no profile exist
	   in this case it can be use only for default values */
	RshareSettings::Create ();

	/* Setup The GUI Stuff */
	Rshare rshare(args, argc, argv, 
		QString::fromUtf8(RsInit::RsConfigDirectory().c_str()));

	std::string url = RsInit::getRetroShareLink();
	if (!url.empty()) {
		/* start with RetroShare link */
		EventReceiver eventReceiver;
		if (eventReceiver.sendRetroShareLink(QString::fromStdString(url))) {
			return 0;
		}

		/* Start RetroShare */
	}

	QSplashScreen splashScreen(QPixmap(":/images/splash.png")/* , Qt::WindowStaysOnTopHint*/);

	switch (initResult) {
	case RS_INIT_OK:
		{
			/* Login Dialog */
			/* check for existing Certificate */
			StartDialog *sd = NULL;
			bool genCert = false;
			std::list<std::string> accountIds;
			if (RsInit::getAccountIds(accountIds) && (accountIds.size() > 0))
			{
				sd = new StartDialog();
				sd->show();

				while(sd -> isVisible())
				{
					rshare.processEvents();
#ifdef WIN32
					Sleep(10);
#else // __LINUX__
					usleep(10000);
#endif
				}

				/* if we're logged in */
				genCert = sd->requestedNewCert();
				delete (sd);
			}
			else
			{
				genCert = true;
			}

			if (genCert)
			{
				GenCertDialog gd;
				gd.exec ();
			}

			splashScreen.show();
		}
		break;
	case RS_INIT_HAVE_ACCOUNT:
		{
			splashScreen.show();
			splashScreen.showMessage(rshare.translate("SplashScreen", "Load profile"), Qt::AlignHCenter | Qt::AlignBottom);

			std::string preferredId, gpgId, gpgName, gpgEmail, sslName;
			RsInit::getPreferedAccountId(preferredId);

			if (RsInit::getAccountDetails(preferredId, gpgId, gpgName, gpgEmail, sslName))
			{
				RsInit::SelectGPGAccount(gpgId);
			}

			// true: note auto-login is active
			std::string lockFile;
			int retVal = RsInit::LockAndLoadCertificates(true, lockFile);
			switch(retVal)
			{
				case 0:	break;
				case 1:	QMessageBox::warning(	0,
												QObject::tr("Multiple instances"),
												QObject::tr("Another RetroShare using the same profile is "
												"already running on your system. Please close "
												"that instance first\n Lock file:\n") +
												QString::fromStdString(lockFile));
						return 1;
				case 2:	QMessageBox::critical(	0,
												QObject::tr("Multiple instances"),
												QObject::tr("An unexpected error occurred when Retroshare"
												"tried to acquire the single instance lock\n Lock file:\n") +
												QString::fromStdString(lockFile));
						return 1;
				case 3: QMessageBox::critical(	0,
												QObject::tr("Login Failure"),
												QObject::tr("Maybe password is wrong") );
						return 1;
				default: std::cerr << "StartDialog::loadCertificates() unexpected switch value " << retVal << std::endl;
			}
		}
		break;
	default:
		/* Unexpected return code */
		std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl;
		QMessageBox::warning(0, QObject::tr("RetroShare"), QObject::tr("An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult));
		return 1;
	}

	/* recreate global settings object, now with correct path */
	RshareSettings::Create(true);
	Rshare::resetLanguageAndStyle();

	SoundManager::create();

	splashScreen.showMessage(rshare.translate("SplashScreen", "Load configuration"), Qt::AlignHCenter | Qt::AlignBottom);

	/* stop Retroshare if startup fails */
	if (!rsicontrol->StartupRetroShare())
	{
		std::cerr << "libretroshare failed to startup!" << std::endl;
		return 1;
	}


	Rshare::initPlugins();

	splashScreen.showMessage(rshare.translate("SplashScreen", "Create interface"), Qt::AlignHCenter | Qt::AlignBottom);

	RsharePeerSettings::Create();

	Emoticons::load();

	if (Settings->value(QString::fromUtf8("FirstRun"), true).toBool()) {
		splashScreen.hide();

		Settings->setValue(QString::fromUtf8("FirstRun"), false);

#ifdef __APPLE__
		/* For OSX, we set the default to "cleanlooks", as the AQUA style hides some input boxes 
		 * only on the first run - as the user might want to change it ;)
		 */
		QString osx_style("cleanlooks");
		Rshare::setStyle(osx_style);
		Settings->setInterfaceStyle(osx_style);
#endif

// This is now disabled - as it doesn't add very much.
// Need to make sure that defaults are sensible!
#ifdef ENABLE_QUICKSTART_WIZARD
		QuickStartWizard qstartWizard;
		qstartWizard.exec();
#endif

	}

	MainWindow *w = MainWindow::Create ();
	splashScreen.finish(w);

	EventReceiver *eventReceiver = NULL;
	if (Settings->getRetroShareProtocol()) {
		/* Create event receiver */
		eventReceiver = new EventReceiver;
		if (eventReceiver->start()) {
			QObject::connect(eventReceiver, SIGNAL(linkReceived(const QUrl&)), w, SLOT(linkActivated(const QUrl&)));
		}
	}

	if (!url.empty()) {
		/* Now use link from the command line, because no RetroShare was running */
		RetroShareLink link(QString::fromStdString(url));
		if (link.valid()) {
			w->linkActivated(link.toUrl());
		}
	}

	// I'm using a signal to transfer the hashing info to the mainwindow, because Qt schedules signals properly to
	// avoid clashes between infos from threads.
	//

	qRegisterMetaType<FileDetail>("FileDetail") ;

	std::cerr << "connecting signals and slots" << std::endl ;
	QObject::connect(notify,SIGNAL(gotTurtleSearchResult(qulonglong,FileDetail)),w->searchDialog	,SLOT(updateFiles(qulonglong,FileDetail))) ;
	QObject::connect(notify,SIGNAL(diskFull(int,int))						,w                   		,SLOT(displayDiskSpaceWarning(int,int))) ;
	QObject::connect(notify,SIGNAL(filesPreModChanged(bool))          ,w->sharedfilesDialog		,SLOT(preModDirectories(bool)          )) ;
	QObject::connect(notify,SIGNAL(filesPostModChanged(bool))         ,w->sharedfilesDialog		,SLOT(postModDirectories(bool)         )) ;
	QObject::connect(notify,SIGNAL(filesPostModChanged(bool))         ,w                            ,SLOT(postModDirectories(bool)         )) ;
	QObject::connect(notify,SIGNAL(transfersChanged())                ,w->transfersDialog  		,SLOT(insertTransfers()                )) ;
	QObject::connect(notify,SIGNAL(publicChatChanged(int))            ,w->friendsDialog      		,SLOT(publicChatChanged(int)           ));
	QObject::connect(notify,SIGNAL(privateChatChanged(int, int))      ,w                   		,SLOT(privateChatChanged(int, int)     ));
	QObject::connect(notify,SIGNAL(neighboursChanged())               ,w->networkDialog    		,SLOT(insertConnect()                  )) ;
	QObject::connect(notify,SIGNAL(messagesChanged())                 ,w->messagesDialog   		,SLOT(insertMessages()                 )) ;
	QObject::connect(notify,SIGNAL(messagesTagsChanged())             ,w->messagesDialog   		,SLOT(messagesTagsChanged()            )) ;
	QObject::connect(notify,SIGNAL(messagesChanged())                 ,w                   		,SLOT(updateMessages()                 )) ;
	QObject::connect(notify,SIGNAL(forumsChanged())                   ,w                   		,SLOT(updateForums()                   ), Qt::QueuedConnection);
	QObject::connect(notify,SIGNAL(channelsChanged(int))              ,w                   		,SLOT(updateChannels(int)              ), Qt::QueuedConnection);
	QObject::connect(notify,SIGNAL(downloadCompleteCountChanged(int)) ,w                   		,SLOT(updateTransfers(int)             ));

	QObject::connect(notify,SIGNAL(chatStatusChanged(const QString&,const QString&,bool)),w->friendsDialog,SLOT(updatePeerStatusString(const QString&,const QString&,bool)));
	QObject::connect(notify,SIGNAL(ownStatusMessageChanged()),w->friendsDialog,SLOT(loadmypersonalstatus()));

	QObject::connect(notify,SIGNAL(logInfoChanged(const QString&))		,w->networkDialog,SLOT(setLogInfo(QString))) ;
	QObject::connect(notify,SIGNAL(discInfoChanged())						,w->networkDialog,SLOT(updateNewDiscoveryInfo()),Qt::QueuedConnection) ;
	QObject::connect(notify,SIGNAL(errorOccurred(int,int,const QString&)),w,SLOT(displayErrorMessage(int,int,const QString&))) ;

	w->installGroupChatNotifier();

	/* only show window, if not startMinimized */
	if (RsInit::getStartMinimised() || Settings->getStartMinimized())
	{
		splashScreen.close();
	} else {
		w->show();
	}

	/* Startup a Timer to keep the gui's updated */
	QTimer *timer = new QTimer(w);
	timer -> connect(timer, SIGNAL(timeout()), notify, SLOT(UpdateGUI()));
	timer->start(1000);

	notify->enable() ;	// enable notification system after GUI creation, to avoid data races in Qt.

	/* dive into the endless loop */
	int ti = rshare.exec();
	delete w ;

	if (eventReceiver) {
		/* Destroy event receiver */
		delete eventReceiver;
		eventReceiver = NULL;
	}

	/* cleanup */
	ChatDialog::cleanupChat();

	rsicontrol->rsGlobalShutDown();

	delete(soundManager);
	soundManager = NULL;

	Settings->sync();
	delete(Settings);

	return ti ;
}
int main(int argc, char *argv[])
{ 
#ifdef WINDOWS_SYS
	// The current directory of the application is changed when using the native dialog on Windows
	// This is a quick fix until libretroshare is using a absolute path in the portable Version
#if QT_VERSION >= QT_VERSION_CHECK (5, 3, 0)
	// Do we need a solution in v0.6?
#endif
#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) && QT_VERSION < QT_VERSION_CHECK (5, 3, 0)
	typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
	typedef QString (*_qt_filedialog_open_filename_hook)     (QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
	typedef QString (*_qt_filedialog_save_filename_hook)     (QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
	typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options);

	extern Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook;
	extern Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook;
	extern Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook;
	extern Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook;

	qt_filedialog_open_filename_hook = filedialog_open_filename_hook;
	qt_filedialog_open_filenames_hook = filedialog_open_filenames_hook;
	qt_filedialog_save_filename_hook = filedialog_save_filename_hook;
	qt_filedialog_existing_directory_hook = filedialog_existing_directory_hook;
#endif
#if QT_VERSION < QT_VERSION_CHECK (5, 0, 0)
	extern bool Q_GUI_EXPORT qt_use_native_dialogs;
	qt_use_native_dialogs = false;
#endif

	{
		/* Set the current directory to the application dir,
		   because the start dir with autostart from the registry run key is not the exe dir */
		QApplication app(argc, argv);
		QDir::setCurrent(QCoreApplication::applicationDirPath());
	}
#endif

	QStringList args = char_array_to_stringlist(argv+1, argc-1);

    Q_INIT_RESOURCE(images);
    Q_INIT_RESOURCE(icons);

	// This is needed to allocate rsNotify, so that it can be used to ask for PGP passphrase
	//
	RsControl::earlyInitNotificationSystem() ;

	NotifyQt *notify = NotifyQt::Create();
	rsNotify->registerNotifyClient(notify);

	/* RetroShare Core Objects */
	RsInit::InitRsConfig();
	int initResult = RsInit::InitRetroShare(argc, argv);

	if(initResult == RS_INIT_NO_KEYRING)	// happens when we already have accounts, but no pgp key. This is when switching to the openpgp-sdk version.
	{
		QApplication dummyApp (argc, argv); // needed for QMessageBox
		/* Translate into the desired language */
		LanguageSupport::translate(LanguageSupport::defaultLanguageCode());

		QMessageBox msgBox;
		msgBox.setText(QObject::tr("This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software."));
		msgBox.setInformativeText(QObject::tr("Choose between:<br><ul><li><b>Ok</b> to copy the existing keyring from gnupg (safest bet), or </li><li><b>Close without saving</b> to start fresh with an empty keyring (you will be asked to create a new PGP key to work with RetroShare, or import a previously saved pgp keypair). </li><li><b>Cancel</b> to quit and forge a keyring by yourself (needs some PGP skills)</li></ul>"));
		msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Discard | QMessageBox::Cancel);
		msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.setWindowIcon(QIcon(":/icons/logo_128.png"));

		int ret = msgBox.exec();

		if(ret == QMessageBox::Cancel)
			return 0 ;
		if(ret == QMessageBox::Ok)
		{
			if(!RsAccounts::CopyGnuPGKeyrings())
				return 0 ; 

			initResult = RsInit::InitRetroShare(argc, argv);

			displayWarningAboutDSAKeys() ;

		}
		else
			initResult = RS_INIT_OK ;
	}

	if (initResult < 0) {
		/* Error occured */
		QApplication dummyApp (argc, argv); // needed for QMessageBox
		/* Translate into the desired language */
		LanguageSupport::translate(LanguageSupport::defaultLanguageCode());

		displayWarningAboutDSAKeys();

		QMessageBox mb(QMessageBox::Critical, QObject::tr("RetroShare"), "", QMessageBox::Ok);
        mb.setWindowIcon(QIcon(":/icons/logo_128.png"));

		switch (initResult) 
		{
			case RS_INIT_AUTH_FAILED:
				std::cerr << "RsInit::InitRetroShare AuthGPG::InitAuth failed" << std::endl;
				mb.setText(QObject::tr("Initialization failed. Wrong or missing installation of PGP."));
				break;
			default:
				/* Unexpected return code */
				std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl;
				mb.setText(QObject::tr("An unexpected error occurred. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult));
				break;
		}
		mb.exec();
		return 1;
	}

	/* create global settings object
	   path maybe wrong, when no profile exist
	   in this case it can be use only for default values */
	RshareSettings::Create ();

	/* Setup The GUI Stuff */
	Rshare rshare(args, argc, argv, 
		QString::fromUtf8(RsAccounts::ConfigDirectory().c_str()));

	std::string url = RsInit::getRetroShareLink();
	if (!url.empty()) {
		/* start with RetroShare link */
		EventReceiver eventReceiver;
		if (eventReceiver.sendRetroShareLink(QString::fromStdString(url))) {
			return 0;
		}

		/* Start RetroShare */
	}

	QSplashScreen splashScreen(QPixmap(":/images/logo/logo_splash.png")/* , Qt::WindowStaysOnTopHint*/);

	switch (initResult) {
	case RS_INIT_OK:
		{
			/* Login Dialog */
			/* check for existing Certificate */
			bool genCert = false;
			std::list<RsPeerId> accountIds;
			if (RsAccounts::GetAccountIds(accountIds) && (accountIds.size() > 0))
			{
				StartDialog sd;
				if (sd.exec() == QDialog::Rejected) {
					return 1;
				}

				/* if we're logged in */
				genCert = sd.requestedNewCert();
			}
			else
			{
				genCert = true;
			}

			if (genCert)
			{
				GenCertDialog gd(false);
				if (gd.exec () == QDialog::Rejected) {
					return 1;
				}
			}

			splashScreen.show();
		}
		break;
	case RS_INIT_HAVE_ACCOUNT:
		{
			splashScreen.show();
			splashScreen.showMessage(rshare.translate("SplashScreen", "Load profile"), Qt::AlignHCenter | Qt::AlignBottom);

			RsPeerId preferredId;
			RsAccounts::GetPreferredAccountId(preferredId);

			// true: note auto-login is active
			Rshare::loadCertificate(preferredId, true);
		}
		break;
	default:
		/* Unexpected return code */
		std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl;
		QMessageBox::warning(0, QObject::tr("RetroShare"), QObject::tr("An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult));
		return 1;
	}

	/* recreate global settings object, now with correct path */
	RshareSettings::Create(true);
	Rshare::resetLanguageAndStyle();

	SoundManager::create();

	splashScreen.showMessage(rshare.translate("SplashScreen", "Load configuration"), Qt::AlignHCenter | Qt::AlignBottom);

	/* stop Retroshare if startup fails */
	if (!RsControl::instance()->StartupRetroShare())
	{
		std::cerr << "libretroshare failed to startup!" << std::endl;
		return 1;
	}


	Rshare::initPlugins();

	splashScreen.showMessage(rshare.translate("SplashScreen", "Create interface"), Qt::AlignHCenter | Qt::AlignBottom);

	RsharePeerSettings::Create();

	Emoticons::load();

	if (Settings->value(QString::fromUtf8("FirstRun"), true).toBool()) {
		splashScreen.hide();

		Settings->setValue(QString::fromUtf8("FirstRun"), false);

		SoundManager::initDefault();

#ifdef __APPLE__
		/* For OSX, we set the default to "cleanlooks", as the AQUA style hides some input boxes 
		 * only on the first run - as the user might want to change it ;)
		 */
		QString osx_style("cleanlooks");
		Rshare::setStyle(osx_style);
		Settings->setInterfaceStyle(osx_style);
#endif

// This is now disabled - as it doesn't add very much.
// Need to make sure that defaults are sensible!
#ifdef ENABLE_QUICKSTART_WIZARD
		QuickStartWizard qstartWizard;
		qstartWizard.exec();
#endif

	}

	MainWindow *w = MainWindow::Create ();
	splashScreen.finish(w);

	EventReceiver *eventReceiver = NULL;
	if (Settings->getRetroShareProtocol()) {
		/* Create event receiver */
		eventReceiver = new EventReceiver;
		if (eventReceiver->start()) {
			QObject::connect(eventReceiver, SIGNAL(linkReceived(const QUrl&)), w, SLOT(retroshareLinkActivated(const QUrl&)));
		}
	}

	if (!url.empty()) {
		/* Now use link from the command line, because no RetroShare was running */
		RetroShareLink link(QString::fromStdString(url));
		if (link.valid()) {
			w->retroshareLinkActivated(link.toUrl());
		}
	}

	// I'm using a signal to transfer the hashing info to the mainwindow, because Qt schedules signals properly to
	// avoid clashes between infos from threads.
	//

	qRegisterMetaType<FileDetail>("FileDetail") ;
	qRegisterMetaType<RsPeerId>("RsPeerId") ;

	std::cerr << "connecting signals and slots" << std::endl ;
	QObject::connect(notify,SIGNAL(gotTurtleSearchResult(qulonglong,FileDetail)),w->transfersDialog->searchDialog	,SLOT(updateFiles(qulonglong,FileDetail))) ;
	QObject::connect(notify,SIGNAL(deferredSignatureHandlingRequested()),notify,SLOT(handleSignatureEvent()),Qt::QueuedConnection) ;
	QObject::connect(notify,SIGNAL(chatLobbyTimeShift(int)),notify,SLOT(handleChatLobbyTimeShift(int)),Qt::QueuedConnection) ;
	QObject::connect(notify,SIGNAL(diskFull(int,int))						,w                   		,SLOT(displayDiskSpaceWarning(int,int))) ;
	QObject::connect(notify,SIGNAL(filesPostModChanged(bool))         ,w                         ,SLOT(postModDirectories(bool)         )) ;
	QObject::connect(notify,SIGNAL(transfersChanged())                ,w->transfersDialog  		,SLOT(insertTransfers()                )) ;
	QObject::connect(notify,SIGNAL(publicChatChanged(int))            ,w->friendsDialog      		,SLOT(publicChatChanged(int)           ));
	QObject::connect(notify,SIGNAL(neighboursChanged())               ,w->friendsDialog->networkDialog    		,SLOT(securedUpdateDisplay())) ;

	QObject::connect(notify,SIGNAL(chatStatusChanged(const QString&,const QString&,bool)),w->friendsDialog,SLOT(updatePeerStatusString(const QString&,const QString&,bool)));
	QObject::connect(notify,SIGNAL(ownStatusMessageChanged()),w->friendsDialog,SLOT(loadmypersonalstatus()));

	QObject::connect(notify,SIGNAL(logInfoChanged(const QString&))		,w->friendsDialog->networkDialog,SLOT(setLogInfo(QString))) ;
	QObject::connect(notify,SIGNAL(discInfoChanged())						,w->friendsDialog->networkView,SLOT(update()),Qt::QueuedConnection) ;
	QObject::connect(notify,SIGNAL(errorOccurred(int,int,const QString&)),w,SLOT(displayErrorMessage(int,int,const QString&))) ;

	w->installGroupChatNotifier();

	/* only show window, if not startMinimized */
	if (RsInit::getStartMinimised() || Settings->getStartMinimized())
	{
		splashScreen.close();
	} else {
		w->show();
	}

	/* Startup a Timer to keep the gui's updated */
	QTimer *timer = new QTimer(w);
	timer -> connect(timer, SIGNAL(timeout()), notify, SLOT(UpdateGUI()));
	timer->start(1000);

	notify->enable() ;	// enable notification system after GUI creation, to avoid data races in Qt.

    WebuiPage::checkStartWebui();

	/* dive into the endless loop */
	int ti = rshare.exec();
	delete w ;

    WebuiPage::checkShutdownWebui();

	if (eventReceiver) {
		/* Destroy event receiver */
		delete eventReceiver;
		eventReceiver = NULL;
	}

	/* cleanup */
	ChatDialog::cleanupChat();
#ifdef RS_ENABLE_GXS
	RsGxsUpdateBroadcast::cleanup();
#endif

	RsControl::instance()->rsGlobalShutDown();

	delete(soundManager);
	soundManager = NULL;

	Settings->sync();
	delete(Settings);

	return ti ;
}
Exemple #12
0
int main(int argc, char *argv[])
{ 
#ifdef WINDOWS_SYS
	{
		/* Set the current directory to the application dir,
		   because the start dir with autostart from the registry run key is not the exe dir */
		QApplication app(argc, argv);
		QDir::setCurrent(QCoreApplication::applicationDirPath());
	}
#endif

  QStringList args = char_array_to_stringlist(argv+1, argc-1);
  
  Q_INIT_RESOURCE(images);

	rsiface = NULL;

	NotifyQt *notify = NotifyQt::Create();
	createRsIface(*notify);
	createRsControl(*rsiface, *notify);

        /* RetroShare Core Objects */
	RsInit::InitRsConfig();
	int initResult = RsInit::InitRetroShare(argc, argv);

	if (initResult < 0) {
		/* Error occured */
		QApplication dummyApp (argc, argv); // needed for QMessageBox
		QMessageBox mb(QMessageBox::Critical, QObject::tr("RetroShare"), "", QMessageBox::Ok);
		mb.setWindowIcon(QIcon(":/images/rstray3.png"));

		switch (initResult) {
		case RS_INIT_AUTH_FAILED:
			std::cerr << "RsInit::InitRetroShare AuthGPG::InitAuth failed" << std::endl;
			mb.setText(QObject::tr("Inititialize failed. Wrong or missing installation of gpg."));
			break;
		default:
			/* Unexpected return code */
			std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl;
			mb.setText(QObject::tr("An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult));
			break;
		}
		mb.exec();
		return 1;
	}

	/* create global settings object
	   path maybe wrong, when no profile exist
	   in this case it can be use only for default values */
	RshareSettings::Create ();

	/* Setup The GUI Stuff */
	Rshare rshare(args, argc, argv, 
		QString::fromStdString(RsInit::RsConfigDirectory()));

	std::string url = RsInit::getRetroShareLink();
	if (!url.empty()) {
		/* start with RetroShare link */
		EventReceiver eventReceiver;
		if (eventReceiver.sendRetroShareLink(QString::fromStdString(url))) {
			return 0;
		}

		/* Start RetroShare */
	}

	QSplashScreen splashScreen(QPixmap(":/images/splash.png")/* , Qt::WindowStaysOnTopHint*/);

	switch (initResult) {
	case RS_INIT_OK:
		{
			/* Login Dialog */
			/* check for existing Certificate */
			std::string userName;

			StartDialog *sd = NULL;
			bool genCert = false;
			std::list<std::string> accountIds;
			if (RsInit::getAccountIds(accountIds) && (accountIds.size() > 0))
			{
				sd = new StartDialog();
				sd->show();

				while(sd -> isVisible())
				{
					rshare.processEvents();
#ifdef WIN32
					Sleep(10);
#else // __LINUX__
					usleep(10000);
#endif
				}

				/* if we're logged in */
				genCert = sd->requestedNewCert();
				delete (sd);
			}
			else
			{
				genCert = true;
			}

			if (genCert)
			{
				GenCertDialog gd;
				gd.exec ();
			}

			splashScreen.show();
		}
		break;
	case RS_INIT_HAVE_ACCOUNT:
		{
			splashScreen.show();
			splashScreen.showMessage(rshare.translate("SplashScreen", "Load profile"), Qt::AlignHCenter | Qt::AlignBottom);

			std::string preferredId, gpgId, gpgName, gpgEmail, sslName;
			RsInit::getPreferedAccountId(preferredId);

			if (RsInit::getAccountDetails(preferredId, gpgId, gpgName, gpgEmail, sslName))
			{
				RsInit::SelectGPGAccount(gpgId);
			}

			// true: note auto-login is active
                        std::string lockFile;
                        int retVal = RsInit::LockAndLoadCertificates(true, lockFile);
			switch(retVal)
			{
				case 0:	break;
				case 1:	QMessageBox::warning(	0,
												QObject::tr("Multiple instances"),
												QObject::tr("Another RetroShare using the same profile is "
                                                                                                                "already running on your system. Please close "
                                                                                                                "that instance first\n Lock file:\n") +
                                                                                                                QString::fromStdString(lockFile));
						return 1;
				case 2:	QMessageBox::critical(	0,
												QObject::tr("Multiple instances"),
												QObject::tr("An unexpected error occurred when Retroshare"
                                                                                                                     "tried to acquire the single instance lock\n Lock file:\n") +
                                                                                                                     QString::fromStdString(lockFile));
						return 1;
				case 3: QMessageBox::critical(	0,
												QObject::tr("Login Failure"),
												QObject::tr("Maybe password is wrong") );
						return 1;
				default: std::cerr << "StartDialog::loadCertificates() unexpected switch value " << retVal << std::endl;
			}
		}
		break;
	default:
		/* Unexpected return code */
		std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl;
		QMessageBox::warning(0, QObject::tr("RetroShare"), QObject::tr("An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult));
		return 1;
	}

	splashScreen.showMessage(rshare.translate("SplashScreen", "Load configuration"), Qt::AlignHCenter | Qt::AlignBottom);

	rsicontrol->StartupRetroShare();

	splashScreen.showMessage(rshare.translate("SplashScreen", "Create interface"), Qt::AlignHCenter | Qt::AlignBottom);

	/* recreate global settings object, now with correct path */
	RshareSettings::Create ();
	RsharePeerSettings::Create();

#ifdef MINIMAL_RSGUI
	MessengerWindow::showYourself();

	rshare.setQuitOnLastWindowClosed(true);

	splashScreen.hide();
#else
	Emoticons::load();

	if (Settings->value(QString::fromUtf8("FirstRun"), true).toBool()) {
		splashScreen.hide();

		Settings->setValue(QString::fromUtf8("FirstRun"), false);
		QuickStartWizard qstartWizard;
		qstartWizard.exec();
	}

	MainWindow *w = MainWindow::Create ();
	splashScreen.finish(w);

	EventReceiver *eventReceiver = NULL;
	if (Settings->getRetroShareProtocol()) {
		/* Create event receiver */
		eventReceiver = new EventReceiver;
		if (eventReceiver->start()) {
			QObject::connect(eventReceiver, SIGNAL(linkReceived(const QUrl&)), w, SLOT(linkActivated(const QUrl&)));
		}
	}

	if (!url.empty()) {
		/* Now use link from the command line, because no RetroShare was running */
		RetroShareLink link(QString::fromStdString(url));
		if (link.valid()) {
			w->linkActivated(link.toUrl());
		}
	}

	// I'm using a signal to transfer the hashing info to the mainwindow, because Qt schedules signals properly to
	// avoid clashes between infos from threads.
	//

	qRegisterMetaType<FileDetail>("FileDetail") ;

	std::cerr << "connecting signals and slots" << std::endl ;
	QObject::connect(notify,SIGNAL(gotTurtleSearchResult(qulonglong,FileDetail)),w->searchDialog	,SLOT(updateFiles(qulonglong,FileDetail))) ;
	QObject::connect(notify,SIGNAL(diskFull(int,int))						,w                   		,SLOT(displayDiskSpaceWarning(int,int))) ;
	QObject::connect(notify,SIGNAL(filesPreModChanged(bool))          ,w->sharedfilesDialog		,SLOT(preModDirectories(bool)          )) ;
	QObject::connect(notify,SIGNAL(filesPostModChanged(bool))         ,w->sharedfilesDialog		,SLOT(postModDirectories(bool)         )) ;
	QObject::connect(notify,SIGNAL(filesPostModChanged(bool))         ,w                            ,SLOT(postModDirectories(bool)         )) ;
	QObject::connect(notify,SIGNAL(transfersChanged())                ,w->transfersDialog  		,SLOT(insertTransfers()                )) ;
	QObject::connect(notify,SIGNAL(friendsChanged())                  ,w->friendsDialog      		,SLOT(insertPeers()                    )) ;
	QObject::connect(notify,SIGNAL(publicChatChanged(int))            ,w->friendsDialog      		,SLOT(publicChatChanged(int)           ));
	QObject::connect(notify,SIGNAL(groupsChanged(int))                ,w->friendsDialog      		,SLOT(groupsChanged(int)               ));
	QObject::connect(notify,SIGNAL(privateChatChanged(int, int))      ,w                   		,SLOT(privateChatChanged(int, int)     ));
	QObject::connect(notify,SIGNAL(neighboursChanged())               ,w->networkDialog    		,SLOT(insertConnect()                  )) ;
	QObject::connect(notify,SIGNAL(messagesChanged())                 ,w->messagesDialog   		,SLOT(insertMessages()                 )) ;
	QObject::connect(notify,SIGNAL(messagesTagsChanged())             ,w->messagesDialog   		,SLOT(messagesTagsChanged()            )) ;
	QObject::connect(notify,SIGNAL(messagesChanged())                 ,w                   		,SLOT(updateMessages()                 )) ;
	QObject::connect(notify,SIGNAL(forumsChanged())                   ,w                   		,SLOT(updateForums()                   ), Qt::QueuedConnection);
	QObject::connect(notify,SIGNAL(channelsChanged(int))              ,w                   		,SLOT(updateChannels(int)              ), Qt::QueuedConnection);
	QObject::connect(notify,SIGNAL(downloadCompleteCountChanged(int)) ,w                   		,SLOT(updateTransfers(int)             ));

	QObject::connect(notify,SIGNAL(chatStatusChanged(const QString&,const QString&,bool)),w->friendsDialog,SLOT(updatePeerStatusString(const QString&,const QString&,bool)));
	QObject::connect(notify,SIGNAL(ownStatusMessageChanged()),w->friendsDialog,SLOT(loadmypersonalstatus()));

	QObject::connect(notify,SIGNAL(logInfoChanged(const QString&))		,w->networkDialog,SLOT(setLogInfo(QString))) ;
	QObject::connect(notify,SIGNAL(discInfoChanged())						,w->networkDialog,SLOT(updateNewDiscoveryInfo()),Qt::QueuedConnection) ;
	QObject::connect(notify,SIGNAL(errorOccurred(int,int,const QString&)),w,SLOT(displayErrorMessage(int,int,const QString&))) ;

	QObject::connect(w->friendsDialog,SIGNAL(friendsUpdated()),w->networkDialog,SLOT(insertConnect())) ;

	w->installGroupChatNotifier();

	/* only show window, if not startMinimized */
	if (RsInit::getStartMinimised() || Settings->getStartMinimized())
	{
		splashScreen.close();
	} else {
		w->show();
	}

	/* Startup a Timer to keep the gui's updated */
	QTimer *timer = new QTimer(w);
	timer -> connect(timer, SIGNAL(timeout()), notify, SLOT(UpdateGUI()));
	timer->start(1000);
#endif // MINIMAL_RSGUI

	/* dive into the endless loop */
	int ti = rshare.exec();
#ifndef MINIMAL_RSGUI
	delete w ;

	if (eventReceiver) {
		/* Destroy event receiver */
		delete eventReceiver;
		eventReceiver = NULL;
	}

	/* cleanup */
	PopupChatDialog::cleanupChat();
#endif // MINIMAL_RSGUI

	rsicontrol->rsGlobalShutDown();

	Settings->sync();
	delete Settings;

	return ti ;
}
void SourceNavigator::compiler_compileDone(bool bOk)
{
   blockSignals(true);
   updateFiles(bOk);
   blockSignals(false);
}
Exemple #14
0
  //Called when a new command is sent to me
void FuseTracker::gotCommand( FuseCppInterface::NotableAction action, 
                              QString path )
{
  int rm;
  int add;
  QString my_path;
  bool avoid_update = false;

    //If the path is doubling up on the dupfs sync, then kill one
  path = path.replace( RegEx_Dup, "");
  my_path = QString("%1%2").arg( Mounted).arg( path).replace( RegEx_Special, "\\\\\\1");

    //handle an actino
  switch ( action )
  {
      //Delete
    case FuseCppInterface::UNLINK:
    case FuseCppInterface::RMDIR:
      addStatus( ADDING_ITEMS );

        //Run the svn command
      rm = runCmd( QString("/usr/bin/svn remove %1").arg(my_path) );

        //Add this new item
      if ( rm != 0 )
        Updated_Items.remove(my_path);
      break;

      //Add new files
    case FuseCppInterface::SYMLINK:
    case FuseCppInterface::HARDLINK:

    case FuseCppInterface::MKNOD:
    case FuseCppInterface::MKDIR:
    case FuseCppInterface::CREATE:
    case FuseCppInterface::OPEN:
      addStatus( ADDING_ITEMS );

        //Run the svn command
      add = runCmd( QString("/usr/bin/svn add %1").arg(my_path) );

        //Add this new item
      if ( add == 0 )
        Updated_Items[my_path] = OrmLight();
      break;

      //These operations mean we need to update our data at some point
    case FuseCppInterface::CHMOD:
    case FuseCppInterface::CHOWN:
    case FuseCppInterface::TRUNCATE:
    case FuseCppInterface::FTRUNCATE:
    case FuseCppInterface::UTIMES:
    case FuseCppInterface::WRITE:
    case FuseCppInterface::FLUSH:
    case FuseCppInterface::CLOSE:
    case FuseCppInterface::FSYNC:
    case FuseCppInterface::SETXATTR:
    case FuseCppInterface::REMOVEXATTR:
        //Add this new item for update
      Updated_Items[my_path] = OrmLight();
      break;

      //Handle an svn update
    case FuseCppInterface::SVN_COMMIT:
      //qDebug("Running svn commit");
        //Don't allow this action to cause a new commit
      avoid_update = true;

      removeStatus( SYNC_PUSH_REQUIRED );
      addStatus( SYNC_PUSH );

        //If there aren't any updated items, quit out now
      if ( Updated_Items.count() <= 0 )
        return;

        //handle our sync mode
      if ( Op_Mode == OP_SYNC_MODE )
      {
        updateRev();

          //Conduct an update before we commit to avoid conflicts
        QStringList list = updateFiles();
        if ( list.size() > 0 )
          runCmd( QString("/usr/bin/svn update --force --non-interactive --accept mine-full %1").arg(list.join(" ")));

          //Make a list of all the files to be updated
        QString files = QStringList( Updated_Items.keys() ).join(" ");

          //Make it happen
        runCmd( QString("/usr/bin/svn ci -m \\\"Updated %1 Items\\\" --non-interactive --depth immediates %2").arg( Updated_Items.count() ).arg( files ) );

          //Clear out all the now updated items
        QFile::remove( QString("%1/.dupfs_action_log").
                              arg((*Config)["svn_dir"]));
        Updated_Items.clear();
      }
            //Store a local file of the changes to be made at a later time
      else if ( Op_Mode == OP_OFFLINE_MODE )
      {
          //save my list of files requiring a change to the FS
        QString filename = QString("%1/.dupfs_action_log").
                                arg((*Config)["svn_dir"]);
        Updated_Items.saveToFile( filename );
      }

        //Remove my push stats
      removeStatus( SYNC_PUSH );
      break;

      //Check if its a special command
    case FuseCppInterface::SVN_UPDATE:
      //qDebug("Running svn update");
        //Don't allow this action to cause a new commit
      avoid_update = true;

        //Only do this if we aren't offline
      if ( Op_Mode != OP_OFFLINE_MODE )
      {
        removeStatus( SYNC_PULL_REQUIRED );
        addStatus( SYNC_PULL );

          //Issue my update command
        QStringList list = updateFiles();
        runCmd( QString("/usr/bin/svn update --force --non-interactive --accept mine-full %1").arg(list.join(" ")));

        removeStatus( SYNC_PULL );
      }
      break;


      //not sure, just ignore
    case FuseCppInterface::RENAME:
    default:
      return;
      break;
  };

    //If we got here, we know we got a valid command
    //If timer isn't started, start it and then quit out
  if ( !avoid_update && !Timer_Commit_Started )
  {
    addStatus( SYNC_PUSH_REQUIRED );
    Timer_Count = 0;
    Timer_Commit_Started = true;
  }
}
bool MultiBootPatcher::Impl::patchZip()
{
    std::unordered_set<std::string> excludeFromPass1;

    for (auto const &item : info->patchInfo()->autoPatchers()) {
        auto args = info->patchInfo()->autoPatcherArgs(item);

        auto *ap = pc->createAutoPatcher(item, info, args);
        if (!ap) {
            error = PatcherError::createPatcherCreationError(
                    ErrorCode::AutoPatcherCreateError, item);
            return false;
        }

        // TODO: AutoPatcher::newFiles() is not supported yet

        std::vector<std::string> existingFiles = ap->existingFiles();
        if (existingFiles.empty()) {
            pc->destroyAutoPatcher(ap);
            continue;
        }

        autoPatchers.push_back(ap);

        // AutoPatcher files should be excluded from the first pass
        for (auto const &file : existingFiles) {
            excludeFromPass1.insert(file);
        }
    }

    // Unlike the old patcher, we'll write directly to the new file
    if (!openOutputArchive()) {
        return false;
    }

    if (cancelled) return false;

    FileUtils::ArchiveStats stats;
    auto result = FileUtils::mzArchiveStats(info->filename(), &stats,
                                            std::vector<std::string>());
    if (!result) {
        error = result;
        return false;
    }

    maxBytes = stats.totalSize;

    if (cancelled) return false;

    // +1 for mbtool_recovery (update-binary)
    // +1 for bb-wrapper.sh
    // +1 for info.prop
    maxFiles = stats.files + 3;
    updateFiles(files, maxFiles);

    if (!openInputArchive()) {
        return false;
    }

    // Create temporary dir for extracted files for autopatchers
    std::string tempDir = FileUtils::createTemporaryDir(pc->tempDirectory());

    if (!pass1(zOutput, tempDir, excludeFromPass1)) {
        boost::filesystem::remove_all(tempDir);
        return false;
    }

    if (cancelled) return false;

    // On the second pass, run the autopatchers on the rest of the files

    if (!pass2(zOutput, tempDir, excludeFromPass1)) {
        boost::filesystem::remove_all(tempDir);
        return false;
    }

    boost::filesystem::remove_all(tempDir);

    if (cancelled) return false;

    updateFiles(++files, maxFiles);
    updateDetails("META-INF/com/google/android/update-binary");

    // Add mbtool_recovery
    result = FileUtils::mzAddFile(
            zOutput, "META-INF/com/google/android/update-binary",
            pc->dataDirectory() + "/binaries/android/"
                    + info->device()->architecture() + "/mbtool_recovery");
    if (!result) {
        error = result;
        return false;
    }

    if (cancelled) return false;

    updateFiles(++files, maxFiles);
    updateDetails("multiboot/bb-wrapper.sh");

    // Add bb-wrapper.sh
    result = FileUtils::mzAddFile(
        zOutput, "multiboot/bb-wrapper.sh",
        pc->dataDirectory() + "/scripts/bb-wrapper.sh");
    if (!result) {
        error = result;
        return false;
    }

    if (cancelled) return false;

    updateFiles(++files, maxFiles);
    updateDetails("multiboot/info.prop");

    const std::string infoProp = createInfoProp();
    result = FileUtils::mzAddFile(
            zOutput, "multiboot/info.prop",
            std::vector<unsigned char>(infoProp.begin(), infoProp.end()));
    if (!result) {
        error = result;
        return false;
    }

    if (cancelled) return false;

    return true;
}
/*!
 * \brief First pass of patching operation
 *
 * This performs the following operations:
 *
 * - If the PatchInfo has the `hasBootImage` parameter set to true for the
 *   current file, then patch the boot images and copy them to the output file.
 * - Files needed by an AutoPatcher are extracted to the temporary directory.
 * - Otherwise, the file is copied directly to the output zip.
 */
bool MultiBootPatcher::Impl::pass1(zipFile const zOutput,
                                   const std::string &temporaryDir,
                                   const std::unordered_set<std::string> &exclude)
{
    // Boot image params
    bool hasBootImage = info->patchInfo()->hasBootImage();
    auto piBootImages = info->patchInfo()->bootImages();

    int ret = unzGoToFirstFile(zInput);
    if (ret != UNZ_OK) {
        error = PatcherError::createArchiveError(
                ErrorCode::ArchiveReadHeaderError, std::string());
        return false;
    }

    do {
        if (cancelled) return false;

        unz_file_info64 fi;
        std::string curFile;

        if (!FileUtils::mzGetInfo(zInput, &fi, &curFile)) {
            error = PatcherError::createArchiveError(
                    ErrorCode::ArchiveReadHeaderError, curFile);
            return false;
        }

        updateFiles(++files, maxFiles);
        updateDetails(curFile);

        // Skip files that should be patched and added in pass 2
        if (exclude.find(curFile) != exclude.end()) {
            if (!FileUtils::mzExtractFile(zInput, temporaryDir)) {
                error = PatcherError::createArchiveError(
                        ErrorCode::ArchiveReadDataError, curFile);
                return false;
            }
            continue;
        }

        // Try to patch the patchinfo-defined boot images as well as
        // files that end in a common boot image extension

        bool inList = std::find(piBootImages.begin(), piBootImages.end(),
                                curFile) != piBootImages.end();
        bool isExtImg = boost::ends_with(curFile, ".img");
        bool isExtLok = boost::ends_with(curFile, ".lok");
        // Boot images should be over about 30 MiB. This check is here so the
        // patcher won't try to read a multi-gigabyte system image into RAM
        bool isSizeOK = fi.uncompressed_size <= 30 * 1024 * 1024;

        if (hasBootImage && (inList || isExtImg || isExtLok) && isSizeOK) {
            // Load the file into memory
            std::vector<unsigned char> data;

            if (!FileUtils::mzReadToMemory(zInput, &data,
                                           &laProgressCb, this)) {
                error = PatcherError::createArchiveError(
                        ErrorCode::ArchiveReadDataError, curFile);
                return false;
            }

            // If the file contains the boot image magic string, then
            // assume it really is a boot image and patch it
            if (data.size() >= 512) {
                const char *magic = BootImage::BootMagic;
                unsigned int size = BootImage::BootMagicSize;
                auto end = data.begin() + 512;
                auto it = std::search(data.begin(), end,
                                      magic, magic + size);
                if (it != end) {
                    if (!patchBootImage(&data)) {
                        return false;
                    }

                    // Update total size
                    maxBytes += (data.size() - fi.uncompressed_size);
                }
            }

            auto ret2 = FileUtils::mzAddFile(zOutput, curFile, data);
            if (!ret2) {
                error = ret2;
                return false;
            }

            bytes += data.size();
        } else {
            // Directly copy other files to the output zip

            // Rename the installer for mbtool
            if (curFile == "META-INF/com/google/android/update-binary") {
                curFile = "META-INF/com/google/android/update-binary.orig";
            }

            if (!FileUtils::mzCopyFileRaw(zInput, zOutput, curFile,
                                          &laProgressCb, this)) {
                FLOGW("minizip: Failed to copy raw data: {}", curFile);
                error = PatcherError::createArchiveError(
                        ErrorCode::ArchiveWriteDataError, curFile);
                return false;
            }

            bytes += fi.uncompressed_size;
        }
    } while ((ret = unzGoToNextFile(zInput)) == UNZ_OK);

    if (ret != UNZ_END_OF_LIST_OF_FILE) {
        error = PatcherError::createArchiveError(
                ErrorCode::ArchiveReadHeaderError, std::string());
        return false;
    }

    if (cancelled) return false;

    return true;
}
void SourceNavigator::emulator_machineReady()
{
   blockSignals(true);
   updateFiles(true);
   blockSignals(false);
}