| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665 |
- /*
- * Copyright (C) by Klaas Freitag <freitag@owncloud.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
- #include "owncloudgui.h"
- #include "account.h"
- #include "accountmanager.h"
- #include "accountstate.h"
- #include "application.h"
- #include "callstatechecker.h"
- #include "emojimodel.h"
- #include "fileactivitylistmodel.h"
- #include "folderman.h"
- #include "guiutility.h"
- #include "logbrowser.h"
- #include "logger.h"
- #include "openfilemanager.h"
- #include "owncloudsetupwizard.h"
- #include "progressdispatcher.h"
- #include "settingsdialog.h"
- #include "theme.h"
- #include "wheelhandler.h"
- #include "filedetails/filedetails.h"
- #include "filedetails/shareemodel.h"
- #include "filedetails/sharemodel.h"
- #include "filedetails/sortedsharemodel.h"
- #include "tray/sortedactivitylistmodel.h"
- #include "tray/syncstatussummary.h"
- #include "tray/unifiedsearchresultslistmodel.h"
- #ifdef WITH_LIBCLOUDPROVIDERS
- #include "cloudproviders/cloudprovidermanager.h"
- #endif
- #include <QQmlApplicationEngine>
- #include <QDesktopServices>
- #include <QDir>
- #include <QMessageBox>
- #include <QSignalMapper>
- #ifdef WITH_LIBCLOUDPROVIDERS
- #include <QtDBus/QDBusConnection>
- #include <QtDBus/QDBusInterface>
- #endif
- #include <QQmlEngine>
- #include <QQmlComponent>
- #include <QQmlApplicationEngine>
- #include <QQuickItem>
- #include <QQmlContext>
- namespace OCC {
- Q_LOGGING_CATEGORY(lcOwnCloudGui, "com.nextcloud.owncloudgui")
- const char propertyAccountC[] = "oc_account";
- ownCloudGui::ownCloudGui(Application *parent)
- : QObject(parent)
- , _tray(nullptr)
- , _settingsDialog(nullptr)
- , _logBrowser(nullptr)
- #ifdef WITH_LIBCLOUDPROVIDERS
- , _bus(QDBusConnection::sessionBus())
- #endif
- , _app(parent)
- {
- _tray = Systray::instance();
- _tray->setTrayEngine(new QQmlApplicationEngine(this));
- // for the beginning, set the offline icon until the account was verified
- _tray->setIcon(Theme::instance()->folderOfflineIcon(/*systray?*/ true));
- _tray->show();
- connect(_tray.data(), &QSystemTrayIcon::activated,
- this, &ownCloudGui::slotTrayClicked);
- connect(_tray.data(), &Systray::openHelp,
- this, &ownCloudGui::slotHelp);
- connect(_tray.data(), &Systray::openAccountWizard,
- this, &ownCloudGui::slotNewAccountWizard);
- connect(_tray.data(), &Systray::openSettings,
- this, &ownCloudGui::slotShowSettings);
- connect(_tray.data(), &Systray::shutdown,
- this, &ownCloudGui::slotShutdown);
- ProgressDispatcher *pd = ProgressDispatcher::instance();
- connect(pd, &ProgressDispatcher::progressInfo, this,
- &ownCloudGui::slotUpdateProgress);
- FolderMan *folderMan = FolderMan::instance();
- connect(folderMan, &FolderMan::folderSyncStateChange,
- this, &ownCloudGui::slotSyncStateChange);
- connect(Logger::instance(), &Logger::guiLog,
- this, &ownCloudGui::slotShowTrayMessage);
- connect(Logger::instance(), &Logger::optionalGuiLog,
- this, &ownCloudGui::slotShowOptionalTrayMessage);
- connect(Logger::instance(), &Logger::guiMessage,
- this, &ownCloudGui::slotShowGuiMessage);
- qmlRegisterType<SyncStatusSummary>("com.nextcloud.desktopclient", 1, 0, "SyncStatusSummary");
- qmlRegisterType<EmojiModel>("com.nextcloud.desktopclient", 1, 0, "EmojiModel");
- qmlRegisterType<UserStatusSelectorModel>("com.nextcloud.desktopclient", 1, 0, "UserStatusSelectorModel");
- qmlRegisterType<ActivityListModel>("com.nextcloud.desktopclient", 1, 0, "ActivityListModel");
- qmlRegisterType<FileActivityListModel>("com.nextcloud.desktopclient", 1, 0, "FileActivityListModel");
- qmlRegisterType<SortedActivityListModel>("com.nextcloud.desktopclient", 1, 0, "SortedActivityListModel");
- qmlRegisterType<WheelHandler>("com.nextcloud.desktopclient", 1, 0, "WheelHandler");
- qmlRegisterType<CallStateChecker>("com.nextcloud.desktopclient", 1, 0, "CallStateChecker");
- qmlRegisterType<FileDetails>("com.nextcloud.desktopclient", 1, 0, "FileDetails");
- qmlRegisterType<ShareModel>("com.nextcloud.desktopclient", 1, 0, "ShareModel");
- qmlRegisterType<ShareeModel>("com.nextcloud.desktopclient", 1, 0, "ShareeModel");
- qmlRegisterType<SortedShareModel>("com.nextcloud.desktopclient", 1, 0, "SortedShareModel");
- qmlRegisterUncreatableType<UnifiedSearchResultsListModel>("com.nextcloud.desktopclient", 1, 0, "UnifiedSearchResultsListModel", "UnifiedSearchResultsListModel");
- qmlRegisterUncreatableType<UserStatus>("com.nextcloud.desktopclient", 1, 0, "UserStatus", "Access to Status enum");
- qmlRegisterUncreatableType<Sharee>("com.nextcloud.desktopclient", 1, 0, "Sharee", "Access to Type enum");
- qRegisterMetaTypeStreamOperators<Emoji>();
- qRegisterMetaType<ActivityListModel *>("ActivityListModel*");
- qRegisterMetaType<UnifiedSearchResultsListModel *>("UnifiedSearchResultsListModel*");
- qRegisterMetaType<UserStatus>("UserStatus");
- qRegisterMetaType<SharePtr>("SharePtr");
- qRegisterMetaType<ShareePtr>("ShareePtr");
- qRegisterMetaType<Sharee>("Sharee");
- qmlRegisterSingletonInstance("com.nextcloud.desktopclient", 1, 0, "UserModel", UserModel::instance());
- qmlRegisterSingletonInstance("com.nextcloud.desktopclient", 1, 0, "UserAppsModel", UserAppsModel::instance());
- qmlRegisterSingletonInstance("com.nextcloud.desktopclient", 1, 0, "Theme", Theme::instance());
- qmlRegisterSingletonInstance("com.nextcloud.desktopclient", 1, 0, "Systray", Systray::instance());
- }
- void ownCloudGui::createTray()
- {
- _tray->create();
- }
- #ifdef WITH_LIBCLOUDPROVIDERS
- void ownCloudGui::setupCloudProviders()
- {
- new CloudProviderManager(this);
- }
- bool ownCloudGui::cloudProviderApiAvailable()
- {
- if (!_bus.isConnected()) {
- return false;
- }
- QDBusInterface dbus_iface("org.freedesktop.CloudProviderManager", "/org/freedesktop/CloudProviderManager",
- "org.freedesktop.CloudProvider.Manager1", _bus);
- if (!dbus_iface.isValid()) {
- qCInfo(lcApplication) << "DBus interface unavailable";
- return false;
- }
- return true;
- }
- #endif
- // This should rather be in application.... or rather in ConfigFile?
- void ownCloudGui::slotOpenSettingsDialog()
- {
- // if account is set up, start the configuration wizard.
- if (!AccountManager::instance()->accounts().isEmpty()) {
- if (_settingsDialog.isNull() || QApplication::activeWindow() != _settingsDialog) {
- slotShowSettings();
- } else {
- _settingsDialog->close();
- }
- } else {
- qCInfo(lcApplication) << "No configured folders yet, starting setup wizard";
- slotNewAccountWizard();
- }
- }
- void ownCloudGui::slotOpenMainDialog()
- {
- _tray->showWindow();
- }
- void ownCloudGui::slotTrayClicked(QSystemTrayIcon::ActivationReason reason)
- {
- if (reason == QSystemTrayIcon::DoubleClick && UserModel::instance()->currentUser()->hasLocalFolder()) {
- UserModel::instance()->openCurrentAccountLocalFolder();
- } else if (reason == QSystemTrayIcon::Trigger) {
- if (OwncloudSetupWizard::bringWizardToFrontIfVisible()) {
- // brought wizard to front
- } else if (_tray->raiseDialogs()) {
- // Brings dialogs hidden by other apps to front, returns true if any raised
- } else if (_tray->isOpen()) {
- _tray->hideWindow();
- } else {
- if (AccountManager::instance()->accounts().isEmpty()) {
- this->slotOpenSettingsDialog();
- } else {
- _tray->showWindow();
- }
- }
- }
- // FIXME: Also make sure that any auto updater dialogue https://github.com/owncloud/client/issues/5613
- // or SSL error dialog also comes to front.
- }
- void ownCloudGui::slotSyncStateChange(Folder *folder)
- {
- slotComputeOverallSyncStatus();
- if (!folder) {
- return; // Valid, just a general GUI redraw was needed.
- }
- auto result = folder->syncResult();
- qCInfo(lcApplication) << "Sync state changed for folder " << folder->remoteUrl().toString() << ": " << result.statusString();
- if (result.status() == SyncResult::Success
- || result.status() == SyncResult::Problem
- || result.status() == SyncResult::SyncAbortRequested
- || result.status() == SyncResult::Error) {
- Logger::instance()->enterNextLogFile();
- }
- }
- void ownCloudGui::slotFoldersChanged()
- {
- slotComputeOverallSyncStatus();
- }
- void ownCloudGui::slotOpenPath(const QString &path)
- {
- showInFileManager(path);
- }
- void ownCloudGui::slotAccountStateChanged()
- {
- slotComputeOverallSyncStatus();
- }
- void ownCloudGui::slotTrayMessageIfServerUnsupported(Account *account)
- {
- if (account->serverVersionUnsupported()) {
- slotShowTrayMessage(
- tr("Unsupported Server Version"),
- tr("The server on account %1 runs an unsupported version %2. "
- "Using this client with unsupported server versions is untested and "
- "potentially dangerous. Proceed at your own risk.")
- .arg(account->displayName(), account->serverVersion()));
- }
- }
- void ownCloudGui::slotComputeOverallSyncStatus()
- {
- bool allSignedOut = true;
- bool allPaused = true;
- bool allDisconnected = true;
- QVector<AccountStatePtr> problemAccounts;
- auto setStatusText = [&](const QString &text) {
- // FIXME: So this doesn't do anything? Needs to be revisited
- Q_UNUSED(text)
- // Don't overwrite the status if we're currently syncing
- if (FolderMan::instance()->isAnySyncRunning())
- return;
- //_actionStatus->setText(text);
- };
- foreach (auto a, AccountManager::instance()->accounts()) {
- if (!a->isSignedOut()) {
- allSignedOut = false;
- }
- if (!a->isConnected()) {
- problemAccounts.append(a);
- } else {
- allDisconnected = false;
- }
- }
- foreach (Folder *f, FolderMan::instance()->map()) {
- if (!f->syncPaused()) {
- allPaused = false;
- }
- }
- if (!problemAccounts.empty()) {
- _tray->setIcon(Theme::instance()->folderOfflineIcon(true));
- if (allDisconnected) {
- setStatusText(tr("Disconnected"));
- } else {
- setStatusText(tr("Disconnected from some accounts"));
- }
- #ifdef Q_OS_WIN
- // Windows has a 128-char tray tooltip length limit.
- QStringList accountNames;
- foreach (AccountStatePtr a, problemAccounts) {
- accountNames.append(a->account()->displayName());
- }
- _tray->setToolTip(tr("Disconnected from %1").arg(accountNames.join(QLatin1String(", "))));
- #else
- QStringList messages;
- messages.append(tr("Disconnected from accounts:"));
- foreach (AccountStatePtr a, problemAccounts) {
- QString message = tr("Account %1: %2").arg(a->account()->displayName(), a->stateString(a->state()));
- if (!a->connectionErrors().empty()) {
- message += QLatin1String("\n");
- message += a->connectionErrors().join(QLatin1String("\n"));
- }
- messages.append(message);
- }
- _tray->setToolTip(messages.join(QLatin1String("\n\n")));
- #endif
- return;
- }
- if (allSignedOut) {
- _tray->setIcon(Theme::instance()->folderOfflineIcon(true));
- _tray->setToolTip(tr("Please sign in"));
- setStatusText(tr("Signed out"));
- return;
- } else if (allPaused) {
- _tray->setIcon(Theme::instance()->syncStateIcon(SyncResult::Paused, true));
- _tray->setToolTip(tr("Account synchronization is disabled"));
- setStatusText(tr("Synchronization is paused"));
- return;
- }
- // display the info of the least successful sync (eg. do not just display the result of the latest sync)
- QString trayMessage;
- FolderMan *folderMan = FolderMan::instance();
- Folder::Map map = folderMan->map();
- SyncResult::Status overallStatus = SyncResult::Undefined;
- bool hasUnresolvedConflicts = false;
- FolderMan::trayOverallStatus(map.values(), &overallStatus, &hasUnresolvedConflicts);
- // If the sync succeeded but there are unresolved conflicts,
- // show the problem icon!
- auto iconStatus = overallStatus;
- if (iconStatus == SyncResult::Success && hasUnresolvedConflicts) {
- iconStatus = SyncResult::Problem;
- }
- // If we don't get a status for whatever reason, that's a Problem
- if (iconStatus == SyncResult::Undefined) {
- iconStatus = SyncResult::Problem;
- }
- QIcon statusIcon = Theme::instance()->syncStateIcon(iconStatus, true);
- _tray->setIcon(statusIcon);
- // create the tray blob message, check if we have an defined state
- if (map.count() > 0) {
- #ifdef Q_OS_WIN
- // Windows has a 128-char tray tooltip length limit.
- trayMessage = folderMan->trayTooltipStatusString(overallStatus, hasUnresolvedConflicts, false);
- #else
- QStringList allStatusStrings;
- foreach (Folder *folder, map.values()) {
- QString folderMessage = FolderMan::trayTooltipStatusString(
- folder->syncResult().status(),
- folder->syncResult().hasUnresolvedConflicts(),
- folder->syncPaused());
- allStatusStrings += tr("Folder %1: %2").arg(folder->shortGuiLocalPath(), folderMessage);
- }
- trayMessage = allStatusStrings.join(QLatin1String("\n"));
- #endif
- _tray->setToolTip(trayMessage);
- if (overallStatus == SyncResult::Success || overallStatus == SyncResult::Problem) {
- if (hasUnresolvedConflicts) {
- setStatusText(tr("Unresolved conflicts"));
- } else {
- setStatusText(tr("Up to date"));
- }
- } else if (overallStatus == SyncResult::Paused) {
- setStatusText(tr("Synchronization is paused"));
- } else {
- setStatusText(tr("Error during synchronization"));
- }
- } else {
- _tray->setToolTip(tr("There are no sync folders configured."));
- setStatusText(tr("No sync folders configured"));
- }
- }
- void ownCloudGui::hideAndShowTray()
- {
- _tray->hide();
- _tray->show();
- }
- void ownCloudGui::slotShowTrayMessage(const QString &title, const QString &msg)
- {
- qCDebug(lcOwnCloudGui) << "Going to show notification with title: '" << title << "' and message: '" << msg << "'";
- if (_tray) {
- _tray->showMessage(title, msg);
- } else {
- qCWarning(lcApplication) << "Tray not ready: " << msg;
- }
- }
- void ownCloudGui::slotShowTrayUpdateMessage(const QString &title, const QString &msg, const QUrl &webUrl)
- {
- if(_tray) {
- _tray->showUpdateMessage(title, msg, webUrl);
- } else {
- qCWarning(lcApplication) << "Tray not ready: " << msg;
- }
- }
- void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QString &msg)
- {
- slotShowTrayMessage(title, msg);
- }
- /*
- * open the folder with the given Alias
- */
- void ownCloudGui::slotFolderOpenAction(const QString &alias)
- {
- Folder *f = FolderMan::instance()->folder(alias);
- if (f) {
- qCInfo(lcApplication) << "opening local url " << f->path();
- QUrl url = QUrl::fromLocalFile(f->path());
- #ifdef Q_OS_WIN
- // work around a bug in QDesktopServices on Win32, see i-net
- QString filePath = f->path();
- if (filePath.startsWith(QLatin1String("\\\\")) || filePath.startsWith(QLatin1String("//")))
- url = QUrl::fromLocalFile(QDir::toNativeSeparators(filePath));
- else
- url = QUrl::fromLocalFile(filePath);
- #endif
- QDesktopServices::openUrl(url);
- }
- }
- void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo &progress)
- {
- Q_UNUSED(folder);
- // FIXME: Lots of messages computed for nothing in this method, needs revisiting
- if (progress.status() == ProgressInfo::Discovery) {
- #if 0
- if (!progress._currentDiscoveredRemoteFolder.isEmpty()) {
- _actionStatus->setText(tr("Checking for changes in remote \"%1\"")
- .arg(progress._currentDiscoveredRemoteFolder));
- } else if (!progress._currentDiscoveredLocalFolder.isEmpty()) {
- _actionStatus->setText(tr("Checking for changes in local \"%1\"")
- .arg(progress._currentDiscoveredLocalFolder));
- }
- #endif
- } else if (progress.status() == ProgressInfo::Done) {
- QTimer::singleShot(2000, this, &ownCloudGui::slotComputeOverallSyncStatus);
- }
- if (progress.status() != ProgressInfo::Propagation) {
- return;
- }
- if (progress.totalSize() == 0) {
- qint64 currentFile = progress.currentFile();
- qint64 totalFileCount = qMax(progress.totalFiles(), currentFile);
- QString msg;
- if (progress.trustEta()) {
- msg = tr("Syncing %1 of %2 (%3 left)")
- .arg(currentFile)
- .arg(totalFileCount)
- .arg(Utility::durationToDescriptiveString2(progress.totalProgress().estimatedEta));
- } else {
- msg = tr("Syncing %1 of %2")
- .arg(currentFile)
- .arg(totalFileCount);
- }
- //_actionStatus->setText(msg);
- } else {
- QString totalSizeStr = Utility::octetsToString(progress.totalSize());
- QString msg;
- if (progress.trustEta()) {
- msg = tr("Syncing %1 (%2 left)")
- .arg(totalSizeStr, Utility::durationToDescriptiveString2(progress.totalProgress().estimatedEta));
- } else {
- msg = tr("Syncing %1")
- .arg(totalSizeStr);
- }
- //_actionStatus->setText(msg);
- }
- if (!progress._lastCompletedItem.isEmpty()) {
- QString kindStr = Progress::asResultString(progress._lastCompletedItem);
- QString timeStr = QTime::currentTime().toString("hh:mm");
- QString actionText = tr("%1 (%2, %3)").arg(progress._lastCompletedItem._file, kindStr, timeStr);
- auto *action = new QAction(actionText, this);
- Folder *f = FolderMan::instance()->folder(folder);
- if (f) {
- QString fullPath = f->path() + '/' + progress._lastCompletedItem._file;
- if (QFile(fullPath).exists()) {
- connect(action, &QAction::triggered, this, [this, fullPath] { this->slotOpenPath(fullPath); });
- } else {
- action->setEnabled(false);
- }
- }
- if (_recentItemsActions.length() > 5) {
- _recentItemsActions.takeFirst()->deleteLater();
- }
- _recentItemsActions.append(action);
- }
- }
- void ownCloudGui::slotLogin()
- {
- if (auto account = qvariant_cast<AccountStatePtr>(sender()->property(propertyAccountC))) {
- account->account()->resetRejectedCertificates();
- account->signIn();
- } else {
- auto list = AccountManager::instance()->accounts();
- foreach (const auto &a, list) {
- a->signIn();
- }
- }
- }
- void ownCloudGui::slotLogout()
- {
- auto list = AccountManager::instance()->accounts();
- if (auto account = qvariant_cast<AccountStatePtr>(sender()->property(propertyAccountC))) {
- list.clear();
- list.append(account);
- }
- foreach (const auto &ai, list) {
- ai->signOutByUi();
- }
- }
- void ownCloudGui::slotNewAccountWizard()
- {
- OwncloudSetupWizard::runWizard(qApp, SLOT(slotownCloudWizardDone(int)));
- }
- void ownCloudGui::slotShowGuiMessage(const QString &title, const QString &message)
- {
- auto *msgBox = new QMessageBox;
- msgBox->setWindowFlags(msgBox->windowFlags() | Qt::WindowStaysOnTopHint);
- msgBox->setAttribute(Qt::WA_DeleteOnClose);
- msgBox->setText(message);
- msgBox->setWindowTitle(title);
- msgBox->setIcon(QMessageBox::Information);
- msgBox->open();
- }
- void ownCloudGui::slotShowSettings()
- {
- if (_settingsDialog.isNull()) {
- _settingsDialog = new SettingsDialog(this);
- _settingsDialog->setAttribute(Qt::WA_DeleteOnClose, true);
- _settingsDialog->show();
- }
- raiseDialog(_settingsDialog.data());
- }
- void ownCloudGui::slotSettingsDialogActivated()
- {
- emit isShowingSettingsDialog();
- }
- void ownCloudGui::slotShowSyncProtocol()
- {
- slotShowSettings();
- //_settingsDialog->showActivityPage();
- }
- void ownCloudGui::slotShutdown()
- {
- // explicitly close windows. This is somewhat of a hack to ensure
- // that saving the geometries happens ASAP during a OS shutdown
- // those do delete on close
- if (!_settingsDialog.isNull())
- _settingsDialog->close();
- if (!_logBrowser.isNull())
- _logBrowser->deleteLater();
- _app->quit();
- }
- void ownCloudGui::slotToggleLogBrowser()
- {
- if (_logBrowser.isNull()) {
- // init the log browser.
- _logBrowser = new LogBrowser;
- // ## TODO: allow new log name maybe?
- }
- if (_logBrowser->isVisible()) {
- _logBrowser->hide();
- } else {
- raiseDialog(_logBrowser);
- }
- }
- void ownCloudGui::slotOpenOwnCloud()
- {
- if (auto account = qvariant_cast<AccountPtr>(sender()->property(propertyAccountC))) {
- Utility::openBrowser(account->url());
- }
- }
- void ownCloudGui::slotHelp()
- {
- QDesktopServices::openUrl(QUrl(Theme::instance()->helpUrl()));
- }
- void ownCloudGui::raiseDialog(QWidget *raiseWidget)
- {
- if (raiseWidget && !raiseWidget->parentWidget()) {
- // Qt has a bug which causes parent-less dialogs to pop-under.
- raiseWidget->showNormal();
- raiseWidget->raise();
- raiseWidget->activateWindow();
- #ifdef Q_OS_WIN
- // Windows disallows raising a Window when you're not the active application.
- // Use a common hack to attach to the active application
- const auto activeProcessId = GetWindowThreadProcessId(GetForegroundWindow(), nullptr);
- if (activeProcessId != qApp->applicationPid()) {
- const auto threadId = GetCurrentThreadId();
- // don't step here with a debugger...
- if (AttachThreadInput(threadId, activeProcessId, true))
- {
- const auto hwnd = reinterpret_cast<HWND>(raiseWidget->winId());
- SetForegroundWindow(hwnd);
- SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
- AttachThreadInput(threadId, activeProcessId, false);
- }
- }
- #endif
- }
- }
- void ownCloudGui::slotShowShareDialog(const QString &localPath) const
- {
- _tray->createShareDialog(localPath);
- }
- void ownCloudGui::slotShowFileActivityDialog(const QString &localPath) const
- {
- _tray->createFileActivityDialog(localPath);
- }
- } // end namespace
|