X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fqtui%2Fmainwin.cpp;h=39b1f3892c2b3d0d0411bbb216255ba33e374555;hp=cd4a5fe139413a810accf503937b5c7c5296e465;hb=aec9c711900a443bfa7860fa86c6e9c86b81a3e7;hpb=1cb02004ee5973b89368bd84f234d4652794690d diff --git a/src/qtui/mainwin.cpp b/src/qtui/mainwin.cpp index cd4a5fe1..39b1f389 100644 --- a/src/qtui/mainwin.cpp +++ b/src/qtui/mainwin.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2015 by the Quassel Project * + * Copyright (C) 2005-2018 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -24,18 +24,25 @@ #include #include #include +#include #include +#include #ifdef HAVE_KDE4 -# include -# include # include # include # include # include # include # include -# include +#endif + +#ifdef HAVE_KF5 +# include +# include +# include +# include +# include #endif #ifdef Q_WS_X11 @@ -81,6 +88,7 @@ #include "legacysystemtray.h" #include "msgprocessorstatuswidget.h" #include "nicklistwidget.h" +#include "passwordchangedlg.h" #include "qtuiapplication.h" #include "qtuimessageprocessor.h" #include "qtuisettings.h" @@ -91,20 +99,27 @@ #include "statusnotifieritem.h" #include "toolbaractionprovider.h" #include "topicwidget.h" +#include "transfermodel.h" #include "verticaldock.h" -#ifndef HAVE_KDE4 +#ifndef HAVE_KDE +# ifdef HAVE_QTMULTIMEDIA +# include "qtmultimedianotificationbackend.h" +# endif # ifdef HAVE_PHONON # include "phononnotificationbackend.h" # endif -# ifdef HAVE_LIBSNORE -# include "snorenotificationbackend.h" -# endif # include "systraynotificationbackend.h" # include "taskbarnotificationbackend.h" -#else /* HAVE_KDE4 */ +#else /* HAVE_KDE */ # include "knotificationbackend.h" -#endif /* HAVE_KDE4 */ +#endif /* HAVE_KDE */ +#include "systrayanimationnotificationbackend.h" + + +#ifdef HAVE_LIBSNORE +# include "snorenotificationbackend.h" +#endif #ifdef HAVE_SSL # include "sslinfodlg.h" @@ -128,9 +143,12 @@ #include "settingspages/bufferviewsettingspage.h" #include "settingspages/chatmonitorsettingspage.h" #include "settingspages/chatviewsettingspage.h" +#include "settingspages/chatviewcolorsettingspage.h" #include "settingspages/connectionsettingspage.h" #include "settingspages/coreaccountsettingspage.h" #include "settingspages/coreconnectionsettingspage.h" +#include +#include "settingspages/dccsettingspage.h" #include "settingspages/highlightsettingspage.h" #include "settingspages/identitiessettingspage.h" #include "settingspages/ignorelistsettingspage.h" @@ -140,14 +158,18 @@ #include "settingspages/notificationssettingspage.h" #include "settingspages/topicwidgetsettingspage.h" -#ifndef HAVE_KDE4 +#ifndef HAVE_KDE # include "settingspages/shortcutssettingspage.h" #endif +#ifdef HAVE_SONNET +# include "settingspages/sonnetsettingspage.h" +#endif + + MainWin::MainWin(QWidget *parent) -#ifdef HAVE_KDE4 - : KMainWindow(parent), - _kHelpMenu(new KHelpMenu(this, KGlobal::mainComponent().aboutData())), +#ifdef HAVE_KDE + : KMainWindow(parent), _kHelpMenu(new KHelpMenu(this)), #else : QMainWindow(parent), #endif @@ -156,7 +178,8 @@ MainWin::MainWin(QWidget *parent) _titleSetter(this), _awayLog(0), _layoutLoaded(false), - _activeBufferViewIndex(-1) + _activeBufferViewIndex(-1), + _aboutToQuit(false) { setAttribute(Qt::WA_DeleteOnClose, false); // we delete the mainwin manually @@ -170,6 +193,8 @@ MainWin::MainWin(QWidget *parent) setWindowTitle("Quassel IRC"); setWindowIconText("Quassel IRC"); + // Set the default icon for all windows + QApplication::setWindowIcon(QIcon::fromTheme("quassel")); updateIcon(); } @@ -181,9 +206,13 @@ void MainWin::init() connect(Client::messageModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), SLOT(messagesInserted(const QModelIndex &, int, int))); connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showChannelList(NetworkId)), SLOT(showChannelList(NetworkId))); + connect(Client::instance(), SIGNAL(showChannelList(NetworkId)), SLOT(showChannelList(NetworkId))); + connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showNetworkConfig(NetworkId)), SLOT(showNetworkConfig(NetworkId))); connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showIgnoreList(QString)), SLOT(showIgnoreList(QString))); + connect(Client::instance(), SIGNAL(showIgnoreList(QString)), SLOT(showIgnoreList(QString))); + connect(Client::instance(), SIGNAL(dbUpgradeInProgress(bool)), SLOT(showMigrationWarning(bool))); - connect(Client::coreConnection(), SIGNAL(startCoreSetup(QVariantList)), SLOT(showCoreConfigWizard(QVariantList))); + connect(Client::coreConnection(), SIGNAL(startCoreSetup(QVariantList, QVariantList)), SLOT(showCoreConfigWizard(QVariantList, QVariantList))); connect(Client::coreConnection(), SIGNAL(connectionErrorPopup(QString)), SLOT(handleCoreConnectionError(QString))); connect(Client::coreConnection(), SIGNAL(userAuthenticationRequired(CoreAccount *, bool *, QString)), SLOT(userAuthenticationRequired(CoreAccount *, bool *, QString))); connect(Client::coreConnection(), SIGNAL(handleNoSslInClient(bool *)), SLOT(handleNoSslInClient(bool *))); @@ -203,10 +232,11 @@ void MainWin::init() setupActions(); setupBufferWidget(); setupMenus(); + // setupTransferWidget(); not ready yet + setupChatMonitor(); setupTopicWidget(); - setupNickWidget(); setupInputWidget(); - setupChatMonitor(); + setupNickWidget(); setupViewMenuTail(); setupStatusBar(); setupToolBars(); @@ -214,21 +244,30 @@ void MainWin::init() setupTitleSetter(); setupHotList(); -#ifndef HAVE_KDE4 + _bufferWidget->setFocusProxy(_inputWidget); + _chatMonitorView->setFocusProxy(_inputWidget); + +#ifndef HAVE_KDE +# ifdef HAVE_QTMULTIMEDIA + QtUi::registerNotificationBackend(new QtMultimediaNotificationBackend(this)); +# endif # ifdef HAVE_PHONON QtUi::registerNotificationBackend(new PhononNotificationBackend(this)); # endif -# ifdef HAVE_LIBSNORE - QtUi::registerNotificationBackend(new SnoreNotificationBackend(this)); -# elif !defined(QT_NO_SYSTEMTRAYICON) - QtUi::registerNotificationBackend(new SystrayNotificationBackend(this)); -# endif - QtUi::registerNotificationBackend(new TaskbarNotificationBackend(this)); - -#else /* HAVE_KDE4 */ +#else /* HAVE_KDE */ QtUi::registerNotificationBackend(new KNotificationBackend(this)); -#endif /* HAVE_KDE4 */ +#endif /* HAVE_KDE */ + + +#ifndef QT_NO_SYSTEMTRAYICON + QtUi::registerNotificationBackend(new SystrayAnimationNotificationBackend(this)); +#endif +#ifdef HAVE_LIBSNORE + QtUi::registerNotificationBackend(new SnoreNotificationBackend(this)); +#elif !defined(QT_NO_SYSTEMTRAYICON) && !defined(HAVE_KDE) + QtUi::registerNotificationBackend(new SystrayNotificationBackend(this)); +#endif #ifdef HAVE_INDICATEQT QtUi::registerNotificationBackend(new IndicatorNotificationBackend(this)); @@ -249,7 +288,7 @@ void MainWin::init() setDisconnectedState(); // Disable menus and stuff -#ifdef HAVE_KDE4 +#ifdef HAVE_KDE setAutoSaveSettings(); #endif @@ -295,7 +334,7 @@ void MainWin::saveStateToSettings(UiSettings &s) if (lastBufId.isValid()) s.setValue("LastUsedBufferId", lastBufId.toInt()); -#ifdef HAVE_KDE4 +#ifdef HAVE_KDE saveAutoSaveSettings(); #endif } @@ -307,7 +346,7 @@ void MainWin::restoreStateFromSettings(UiSettings &s) _normalPos = s.value("MainWinPos", pos()).toPoint(); bool maximized = s.value("MainWinMaximized", false).toBool(); -#ifndef HAVE_KDE4 +#ifndef HAVE_KDE restoreGeometry(s.value("MainWinGeometry").toByteArray()); if (maximized) { @@ -334,6 +373,15 @@ void MainWin::restoreStateFromSettings(UiSettings &s) show(); } +QMenu *MainWin::createPopupMenu() +{ + QMenu *popupMenu = QMainWindow::createPopupMenu(); + popupMenu->addSeparator(); + ActionCollection *coll = QtUi::actionCollection("General"); + popupMenu->addAction(coll->action("ToggleMenuBar")); + return popupMenu; +} + void MainWin::updateIcon() { @@ -341,9 +389,8 @@ void MainWin::updateIcon() if (Client::isConnected()) icon = QIcon::fromTheme("quassel", QIcon(":/icons/quassel-128.png")); else - icon = QIcon::fromTheme("quassel-inactive", QIcon(":/icons/quassel-128.png")); + icon = QIcon::fromTheme("inactive-quassel", QIcon(":/icons/inactive-quassel.png")); setWindowIcon(icon); - qApp->setWindowIcon(icon); } @@ -351,15 +398,21 @@ void MainWin::setupActions() { ActionCollection *coll = QtUi::actionCollection("General", tr("General")); // File - coll->addAction("ConnectCore", new Action(QIcon::fromTheme("network-connect"), tr("&Connect to Core..."), coll, + coll->addAction("ConnectCore", new Action(QIcon::fromTheme("connect-quassel", QIcon(":/icons/connect-quassel.png")), tr("&Connect to Core..."), coll, this, SLOT(showCoreConnectionDlg()))); - coll->addAction("DisconnectCore", new Action(QIcon::fromTheme("network-disconnect"), tr("&Disconnect from Core"), coll, + coll->addAction("DisconnectCore", new Action(QIcon::fromTheme("disconnect-quassel", QIcon(":/icons/disconnect-quassel.png")), tr("&Disconnect from Core"), coll, Client::instance(), SLOT(disconnectFromCore()))); + coll->addAction("ChangePassword", new Action(QIcon::fromTheme("dialog-password"), tr("Change &Password..."), coll, + this, SLOT(showPasswordChangeDlg()))); coll->addAction("CoreInfo", new Action(QIcon::fromTheme("help-about"), tr("Core &Info..."), coll, this, SLOT(showCoreInfoDlg()))); coll->addAction("ConfigureNetworks", new Action(QIcon::fromTheme("configure"), tr("Configure &Networks..."), coll, this, SLOT(on_actionConfigureNetworks_triggered()))); - // FIXME: use QKeySequence::Quit once we depend on Qt 4.6 + // QKeySequence::Quit was added in Qt 4.6, and could be used instead. However, that key + // sequence is empty by default on Windows, which would remove Ctrl-Q to quit. It may be best + // to just keep it this way. + // + // See https://doc.qt.io/qt-5/qkeysequence.html coll->addAction("Quit", new Action(QIcon::fromTheme("application-exit"), tr("&Quit"), coll, this, SLOT(quit()), Qt::CTRL + Qt::Key_Q)); @@ -376,19 +429,19 @@ void MainWin::setupActions() coll->addAction("ShowAwayLog", new Action(tr("Show Away Log"), coll, this, SLOT(showAwayLog()))); coll->addAction("ToggleMenuBar", new Action(QIcon::fromTheme("show-menu"), tr("Show &Menubar"), coll, - 0, 0, QKeySequence(Qt::CTRL + Qt::Key_M)))->setCheckable(true); + 0, 0))->setCheckable(true); coll->addAction("ToggleStatusBar", new Action(tr("Show Status &Bar"), coll, 0, 0))->setCheckable(true); -#ifdef HAVE_KDE4 - QAction *fullScreenAct = KStandardAction::fullScreen(this, SLOT(onFullScreenToggled()), this, coll); +#ifdef HAVE_KDE + _fullScreenAction = KStandardAction::fullScreen(this, SLOT(onFullScreenToggled()), this, coll); #else - QAction *fullScreenAct = new Action(QIcon::fromTheme("view-fullscreen"), tr("&Full Screen Mode"), coll, + _fullScreenAction = new Action(QIcon::fromTheme("view-fullscreen"), tr("&Full Screen Mode"), coll, this, SLOT(onFullScreenToggled()), QKeySequence(Qt::Key_F11)); - fullScreenAct->setCheckable(true); + _fullScreenAction->setCheckable(true); + coll->addAction("ToggleFullScreen", _fullScreenAction); #endif - coll->addAction("ToggleFullScreen", fullScreenAct); // Settings QAction *configureShortcutsAct = new Action(QIcon::fromTheme("configure-shortcuts"), tr("Configure &Shortcuts..."), coll, @@ -396,18 +449,18 @@ void MainWin::setupActions() configureShortcutsAct->setMenuRole(QAction::NoRole); coll->addAction("ConfigureShortcuts", configureShortcutsAct); - #ifdef Q_OS_MAC +#ifdef Q_OS_MAC QAction *configureQuasselAct = new Action(QIcon::fromTheme("configure"), tr("&Configure Quassel..."), coll, this, SLOT(showSettingsDlg())); configureQuasselAct->setMenuRole(QAction::PreferencesRole); - #else +#else QAction *configureQuasselAct = new Action(QIcon::fromTheme("configure"), tr("&Configure Quassel..."), coll, this, SLOT(showSettingsDlg()), QKeySequence(Qt::Key_F7)); - #endif +#endif coll->addAction("ConfigureQuassel", configureQuasselAct); // Help - QAction *aboutQuasselAct = new Action(QIcon(":/icons/quassel.png"), tr("&About Quassel"), coll, + QAction *aboutQuasselAct = new Action(QIcon::fromTheme("quassel"), tr("&About Quassel"), coll, this, SLOT(showAboutDlg())); aboutQuasselAct->setMenuRole(QAction::AboutRole); coll->addAction("AboutQuassel", aboutQuasselAct); @@ -427,17 +480,52 @@ void MainWin::setupActions() coll->addAction("DebugLog", new Action(QIcon::fromTheme("tools-report-bug"), tr("Debug &Log"), coll, this, SLOT(on_actionDebugLog_triggered()))); coll->addAction("ReloadStyle", new Action(QIcon::fromTheme("view-refresh"), tr("Reload Stylesheet"), coll, - QtUi::style(), SLOT(reload()), QKeySequence::Refresh)); + QtUi::style(), SLOT(reload()), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_R))); coll->addAction("HideCurrentBuffer", new Action(tr("Hide Current Buffer"), coll, this, SLOT(hideCurrentBuffer()), QKeySequence::Close)); + // Text formatting + coll = QtUi::actionCollection("TextFormat", tr("Text formatting")); + + coll->addAction("FormatApplyColor", new Action( + QIcon::fromTheme("format-text-color"), tr("Apply foreground color"), coll, + this, SLOT(on_inputFormatApplyColor_triggered()), + QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_G))); + + coll->addAction("FormatApplyColorFill", new Action( + QIcon::fromTheme("format-fill-color"), tr("Apply background color"), coll, + this, SLOT(on_inputFormatApplyColorFill_triggered()), + QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_B))); + + coll->addAction("FormatClear", new Action( + QIcon::fromTheme("edit-clear"), tr("Clear formatting"), coll, + this, SLOT(on_inputFormatClear_triggered()), + QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C))); + + coll->addAction("FormatBold", new Action( + QIcon::fromTheme("format-text-bold"), tr("Toggle bold"), coll, + this, SLOT(on_inputFormatBold_triggered()), + QKeySequence::Bold)); + + coll->addAction("FormatItalic", new Action( + QIcon::fromTheme("format-text-italic"), tr("Toggle italics"), coll, + this, SLOT(on_inputFormatItalic_triggered()), + QKeySequence::Italic)); + + coll->addAction("FormatUnderline", new Action( + QIcon::fromTheme("format-text-underline"), tr("Toggle underline"), coll, + this, SLOT(on_inputFormatUnderline_triggered()), QKeySequence::Underline)); + // Navigation coll = QtUi::actionCollection("Navigation", tr("Navigation")); coll->addAction("JumpHotBuffer", new Action(tr("Jump to hot chat"), coll, this, SLOT(on_jumpHotBuffer_triggered()), QKeySequence(Qt::META + Qt::Key_A))); + coll->addAction("ActivateBufferFilter", new Action(tr("Activate the buffer search"), coll, + this, SLOT(on_bufferSearch_triggered()), QKeySequence(Qt::CTRL + Qt::Key_S))); + // Jump keys #ifdef Q_OS_MAC const int bindModifier = Qt::ControlModifier | Qt::AltModifier; @@ -508,7 +596,7 @@ void MainWin::setupMenus() _fileMenu = menuBar()->addMenu(tr("&File")); static const QStringList coreActions = QStringList() - << "ConnectCore" << "DisconnectCore" << "CoreInfo"; + << "ConnectCore" << "DisconnectCore" << "ChangePassword" << "CoreInfo"; QAction *coreAction; foreach(QString actionName, coreActions) { @@ -542,7 +630,7 @@ void MainWin::setupMenus() _viewMenu->addAction(coll->action("LockLayout")); _settingsMenu = menuBar()->addMenu(tr("&Settings")); -#ifdef HAVE_KDE4 +#ifdef HAVE_KDE _settingsMenu->addAction(KStandardAction::configureNotifications(this, SLOT(showNotificationsDlg()), this)); _settingsMenu->addAction(KStandardAction::keyBindings(this, SLOT(showShortcutsDlg()), this)); #else @@ -550,9 +638,11 @@ void MainWin::setupMenus() #endif _settingsMenu->addAction(coll->action("ConfigureQuassel")); + _helpMenu = menuBar()->addMenu(tr("&Help")); + _helpMenu->addAction(coll->action("AboutQuassel")); -#ifndef HAVE_KDE4 +#ifndef HAVE_KDE _helpMenu->addAction(coll->action("AboutQt")); #else _helpMenu->addAction(KStandardAction::aboutKDE(_kHelpMenu, SLOT(aboutKDE()), this)); @@ -610,6 +700,8 @@ void MainWin::addBufferView(ClientBufferViewConfig *config) Client::bufferModel()->synchronizeView(view); + dock->setLocked(QtUiSettings().value("LockLayout", false).toBool()); + dock->setWidget(view); dock->setVisible(_layoutLoaded); // don't show before state has been restored @@ -699,7 +791,7 @@ BufferView *MainWin::activeBufferView() const if (_activeBufferViewIndex < 0 || _activeBufferViewIndex >= _bufferViews.count()) return 0; BufferViewDock *dock = _bufferViews.at(_activeBufferViewIndex); - return dock->isActive() ? qobject_cast(dock->widget()) : 0; + return dock->isActive() ? dock->bufferView() : 0; } @@ -708,9 +800,8 @@ void MainWin::changeActiveBufferView(int bufferViewId) if (bufferViewId < 0) return; - BufferView *current = activeBufferView(); - if (current) { - qobject_cast(current->parent())->setActive(false); + if (_activeBufferViewIndex >= 0 && _activeBufferViewIndex < _bufferViews.count()) { + _bufferViews[_activeBufferViewIndex]->setActive(false); _activeBufferViewIndex = -1; } @@ -727,11 +818,50 @@ void MainWin::changeActiveBufferView(int bufferViewId) } +void MainWin::showPasswordChangeDlg() +{ + if(Client::isCoreFeatureEnabled(Quassel::Feature::PasswordChange)) { + PasswordChangeDlg dlg(this); + dlg.exec(); + } + else { + QMessageBox box(QMessageBox::Warning, tr("Feature Not Supported"), + tr("Your Quassel Core does not support this feature"), + QMessageBox::Ok, this); + box.setInformativeText(tr("You need a Quassel Core v0.12.0 or newer in order to be able to remotely change your password.")); + box.exec(); + } +} + + +void MainWin::showMigrationWarning(bool show) +{ + if (show && !_migrationWarning) { + _migrationWarning = new QMessageBox(QMessageBox::Information, + tr("Upgrading..."), + "" + tr("Your database is being upgraded") + "", + QMessageBox::NoButton, this); + _migrationWarning->setInformativeText("

" + + tr("In order to support new features, we need to make changes to your backlog database. This may take a long while.") + + "

" + + tr("Do not exit Quassel until the upgrade is complete!") + + "

"); + _migrationWarning->setStandardButtons(QMessageBox::NoButton); + _migrationWarning->show(); + } + else if (!show && _migrationWarning) { + _migrationWarning->close(); + _migrationWarning->deleteLater(); + _migrationWarning = nullptr; + } +} + + void MainWin::changeActiveBufferView(bool backwards) { - BufferView *current = activeBufferView(); - if (current) - qobject_cast(current->parent())->setActive(false); + if (_activeBufferViewIndex >= 0 && _activeBufferViewIndex < _bufferViews.count()) { + _bufferViews[_activeBufferViewIndex]->setActive(false); + } if (!_bufferViews.count()) return; @@ -822,11 +952,26 @@ void MainWin::on_actionLockLayout_toggled(bool lock) foreach(VerticalDock *dock, docks) { dock->showTitle(!lock); } + + QList nickdocks = findChildren(); + foreach(NickListDock *nickdock, nickdocks) { + nickdock->setLocked(lock); + } + + QList bufferdocks = findChildren(); + foreach(BufferViewDock *bufferdock, bufferdocks) { + bufferdock->setLocked(lock); + } + if (Client::bufferViewManager()) { foreach(ClientBufferViewConfig *config, Client::bufferViewManager()->clientBufferViewConfigs()) { config->setLocked(lock); } } + + _mainToolBar->setMovable(!lock); + _nickToolBar->setMovable(!lock); + QtUiSettings().setValue("LockLayout", lock); } @@ -837,6 +982,7 @@ void MainWin::setupNickWidget() NickListDock *nickDock = new NickListDock(tr("Nicks"), this); nickDock->setObjectName("NickDock"); nickDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + nickDock->setLocked(QtUiSettings().value("LockLayout", false).toBool()); _nickListWidget = new NickListWidget(nickDock); nickDock->setWidget(_nickListWidget); @@ -851,6 +997,8 @@ void MainWin::setupNickWidget() // attach the NickListWidget to the BufferModel and the default selection _nickListWidget->setModel(Client::bufferModel()); _nickListWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel()); + + _nickListWidget->setVisible(false); } @@ -861,7 +1009,6 @@ void MainWin::setupChatMonitor() ChatMonitorFilter *filter = new ChatMonitorFilter(Client::messageModel(), this); _chatMonitorView = new ChatMonitorView(filter, this); - _chatMonitorView->setFocusProxy(_inputWidget); _chatMonitorView->show(); dock->setWidget(_chatMonitorView); dock->hide(); @@ -888,8 +1035,6 @@ void MainWin::setupInputWidget() _inputWidget->setModel(Client::bufferModel()); _inputWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel()); - _bufferWidget->setFocusProxy(_inputWidget); - _inputWidget->inputLine()->installEventFilter(_bufferWidget); connect(_topicWidget, SIGNAL(switchedPlain()), _bufferWidget, SLOT(setFocus())); @@ -914,10 +1059,31 @@ void MainWin::setupTopicWidget() } +void MainWin::setupTransferWidget() +{ + auto dock = new QDockWidget(tr("Transfers"), this); + dock->setObjectName("TransferDock"); + dock->setAllowedAreas(Qt::TopDockWidgetArea|Qt::BottomDockWidgetArea); + + auto view = new QTableView(dock); // to be replaced by the real thing + view->setModel(Client::transferModel()); + dock->setWidget(view); + dock->hide(); // hidden by default + addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical); + + auto action = dock->toggleViewAction(); + action->setText(tr("Show File Transfers")); + action->setIcon(QIcon::fromTheme("download")); + action->setShortcut(QKeySequence(Qt::Key_F6)); + QtUi::actionCollection("General")->addAction("ShowTransferWidget", action); + _viewMenu->addAction(action); +} + + void MainWin::setupViewMenuTail() { _viewMenu->addSeparator(); - _viewMenu->addAction(QtUi::actionCollection("General")->action("ToggleFullScreen")); + _viewMenu->addAction(_fullScreenAction); } @@ -998,7 +1164,7 @@ void MainWin::setupToolBars() setUnifiedTitleAndToolBarOnMac(true); #endif -#ifdef HAVE_KDE4 +#ifdef HAVE_KDE _mainToolBar = new KToolBar("MainToolBar", this, Qt::TopToolBarArea, false, true, true); #else _mainToolBar = new QToolBar(this); @@ -1007,9 +1173,31 @@ void MainWin::setupToolBars() _mainToolBar->setWindowTitle(tr("Main Toolbar")); addToolBar(_mainToolBar); + if (Quassel::runMode() != Quassel::Monolithic) { + ActionCollection *coll = QtUi::actionCollection("General"); + _mainToolBar->addAction(coll->action("ConnectCore")); + _mainToolBar->addAction(coll->action("DisconnectCore")); + } + + _mainToolBar->setMovable(!QtUiSettings().value("LockLayout", false).toBool()); + QtUi::toolBarActionProvider()->addActions(_mainToolBar, ToolBarActionProvider::MainToolBar); _toolbarMenu->addAction(_mainToolBar->toggleViewAction()); +#ifdef HAVE_KDE + _nickToolBar = new KToolBar("NickToolBar", this, Qt::TopToolBarArea, false, true, true); +#else + _nickToolBar = new QToolBar(this); + _nickToolBar->setObjectName("NickToolBar"); +#endif + _nickToolBar->setWindowTitle(tr("Nick Toolbar")); + _nickToolBar->setVisible(false); //default: not visible + addToolBar(_nickToolBar); + _nickToolBar->setMovable(!QtUiSettings().value("LockLayout", false).toBool()); + + QtUi::toolBarActionProvider()->addActions(_nickToolBar, ToolBarActionProvider::NickToolBar); + _toolbarMenu->addAction(_nickToolBar->toggleViewAction()); + #ifdef Q_OS_MAC QtUiSettings uiSettings; @@ -1037,7 +1225,9 @@ void MainWin::connectedToCore() connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigDeleted(int)), this, SLOT(removeBufferView(int))); connect(Client::bufferViewManager(), SIGNAL(initDone()), this, SLOT(loadLayout())); - connect(Client::transferManager(), SIGNAL(transferAdded(const ClientTransfer*)), SLOT(showNewTransferDlg(const ClientTransfer*))); + if (Client::transferManager()) { + connect(Client::transferManager(), SIGNAL(transferAdded(QUuid)), SLOT(showNewTransferDlg(QUuid))); + } setConnectedState(); } @@ -1049,6 +1239,7 @@ void MainWin::setConnectedState() coll->action("ConnectCore")->setEnabled(false); coll->action("DisconnectCore")->setEnabled(true); + coll->action("ChangePassword")->setEnabled(true); coll->action("CoreInfo")->setEnabled(true); foreach(QAction *action, _fileMenu->actions()) { @@ -1102,7 +1293,7 @@ void MainWin::loadLayout() _layoutLoaded = true; return; } - + _nickListWidget->setVisible(true); restoreState(state, accountId); int bufferViewId = s.value(QString("ActiveBufferView-%1").arg(accountId), -1).toInt(); if (bufferViewId >= 0) @@ -1165,12 +1356,14 @@ void MainWin::setDisconnectedState() coll->action("ConnectCore")->setEnabled(true); coll->action("DisconnectCore")->setEnabled(false); coll->action("CoreInfo")->setEnabled(false); + coll->action("ChangePassword")->setEnabled(false); //_viewMenu->setEnabled(false); statusBar()->showMessage(tr("Not connected to core.")); if (_msgProcessorStatusWidget) _msgProcessorStatusWidget->setProgress(0, 0); updateIcon(); systemTray()->setState(SystemTray::Passive); + _nickListWidget->setVisible(false); } @@ -1263,9 +1456,9 @@ void MainWin::showCoreConnectionDlg() } -void MainWin::showCoreConfigWizard(const QVariantList &backends) +void MainWin::showCoreConfigWizard(const QVariantList &backends, const QVariantList &authenticators) { - CoreConfigWizard *wizard = new CoreConfigWizard(Client::coreConnection(), backends, this); + CoreConfigWizard *wizard = new CoreConfigWizard(Client::coreConnection(), backends, authenticators, this); wizard->show(); } @@ -1287,6 +1480,15 @@ void MainWin::showChannelList(NetworkId netId) } +void MainWin::showNetworkConfig(NetworkId netId) +{ + SettingsPageDlg dlg(new NetworksSettingsPage(this), this); + if (netId.isValid()) + qobject_cast(dlg.currentPage())->bufferList_Open(netId); + dlg.exec(); +} + + void MainWin::showIgnoreList(QString newRule) { SettingsPageDlg dlg(new IgnoreListSettingsPage(this), this); @@ -1329,12 +1531,17 @@ void MainWin::showSettingsDlg() //Category: Interface dlg->registerSettingsPage(new AppearanceSettingsPage(dlg)); dlg->registerSettingsPage(new ChatViewSettingsPage(dlg)); + dlg->registerSettingsPage(new ChatViewColorSettingsPage(dlg)); dlg->registerSettingsPage(new ChatMonitorSettingsPage(dlg)); dlg->registerSettingsPage(new ItemViewSettingsPage(dlg)); dlg->registerSettingsPage(new BufferViewSettingsPage(dlg)); dlg->registerSettingsPage(new InputWidgetSettingsPage(dlg)); dlg->registerSettingsPage(new TopicWidgetSettingsPage(dlg)); +#ifdef HAVE_SONNET + dlg->registerSettingsPage(new SonnetSettingsPage(dlg)); +#endif dlg->registerSettingsPage(new HighlightSettingsPage(dlg)); + dlg->registerSettingsPage(new CoreHighlightSettingsPage(dlg)); dlg->registerSettingsPage(new NotificationsSettingsPage(dlg)); dlg->registerSettingsPage(new BacklogSettingsPage(dlg)); @@ -1344,6 +1551,7 @@ void MainWin::showSettingsDlg() dlg->registerSettingsPage(new NetworksSettingsPage(dlg)); dlg->registerSettingsPage(new AliasesSettingsPage(dlg)); dlg->registerSettingsPage(new IgnoreListSettingsPage(dlg)); + // dlg->registerSettingsPage(new DccSettingsPage(dlg)); not ready yet // Category: Remote Cores if (Quassel::runMode() != Quassel::Monolithic) { @@ -1363,11 +1571,11 @@ void MainWin::showAboutDlg() void MainWin::showShortcutsDlg() { -#ifdef HAVE_KDE4 +#ifdef HAVE_KDE KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsDisallowed, this); foreach(KActionCollection *coll, QtUi::actionCollections()) dlg.addCollection(coll, coll->property("Category").toString()); - dlg.exec(); + dlg.configure(true); #else SettingsPageDlg dlg(new ShortcutsSettingsPage(QtUi::actionCollections(), this), this); dlg.exec(); @@ -1375,10 +1583,18 @@ void MainWin::showShortcutsDlg() } -void MainWin::showNewTransferDlg(const ClientTransfer *transfer) +void MainWin::showNewTransferDlg(const QUuid &transferId) { - ReceiveFileDlg *dlg = new ReceiveFileDlg(transfer, this); - dlg->show(); + auto transfer = Client::transferManager()->transfer(transferId); + if (transfer) { + if (transfer->status() == Transfer::Status::New) { + ReceiveFileDlg *dlg = new ReceiveFileDlg(transfer, this); + dlg->show(); + } + } + else { + qWarning() << "Unknown transfer ID" << transferId; + } } @@ -1387,15 +1603,10 @@ void MainWin::onFullScreenToggled() // Relying on QWidget::isFullScreen is discouraged, see the KToggleFullScreenAction docs // Also, one should not use showFullScreen() or showNormal(), as those reset all other window flags - QAction *action = QtUi::actionCollection("General")->action("ToggleFullScreen"); - if (!action) - return; - -#ifdef HAVE_KDE4 - KToggleFullScreenAction *kAct = static_cast(action); - kAct->setFullScreen(this, kAct->isChecked()); +#ifdef HAVE_KDE + static_cast(_fullScreenAction)->setFullScreen(this, _fullScreenAction->isChecked()); #else - if (action->isChecked()) + if (_fullScreenAction->isChecked()) setWindowState(windowState() | Qt::WindowFullScreen); else setWindowState(windowState() & ~Qt::WindowFullScreen); @@ -1448,14 +1659,21 @@ void MainWin::closeEvent(QCloseEvent *event) QtUiSettings s; QtUiApplication *app = qobject_cast qApp; Q_ASSERT(app); - if (!app->isAboutToQuit() && QtUi::haveSystemTray() && s.value("MinimizeOnClose").toBool()) { + // On OSX it can happen that the closeEvent occurs twice. (Especially if packaged with Frameworks) + // This messes up MainWinState/MainWinHidden save/restore. + // It's a bug in Qt: https://bugreports.qt.io/browse/QTBUG-43344 + if (!_aboutToQuit && !app->isAboutToQuit() && QtUi::haveSystemTray() && s.value("MinimizeOnClose").toBool()) { QtUi::hideMainWidget(); event->ignore(); } - else { + else if(!_aboutToQuit) { + _aboutToQuit = true; event->accept(); quit(); } + else { + event->ignore(); + } } @@ -1598,6 +1816,60 @@ void MainWin::connectOrDisconnectFromNet() } +void MainWin::on_inputFormatApplyColor_triggered() +{ + if (!_inputWidget) + return; + + _inputWidget->applyFormatActiveColor(); +} + + +void MainWin::on_inputFormatApplyColorFill_triggered() +{ + if (!_inputWidget) + return; + + _inputWidget->applyFormatActiveColorFill(); +} + + +void MainWin::on_inputFormatClear_triggered() +{ + if (!_inputWidget) + return; + + _inputWidget->clearFormat(); +} + + +void MainWin::on_inputFormatBold_triggered() +{ + if (!_inputWidget) + return; + + _inputWidget->toggleFormatBold(); +} + + +void MainWin::on_inputFormatItalic_triggered() +{ + if (!_inputWidget) + return; + + _inputWidget->toggleFormatItalic(); +} + + +void MainWin::on_inputFormatUnderline_triggered() +{ + if (!_inputWidget) + return; + + _inputWidget->toggleFormatUnderline(); +} + + void MainWin::on_jumpHotBuffer_triggered() { if (!_bufferHotList->rowCount()) @@ -1606,6 +1878,16 @@ void MainWin::on_jumpHotBuffer_triggered() Client::bufferModel()->switchToBuffer(_bufferHotList->hottestBuffer()); } +void MainWin::on_bufferSearch_triggered() +{ + if (_activeBufferViewIndex < 0 || _activeBufferViewIndex >= _bufferViews.count()) { + qWarning() << "Tried to activate filter on invalid bufferview:" << _activeBufferViewIndex; + return; + } + + _bufferViews[_activeBufferViewIndex]->activateFilter(); +} + void MainWin::onJumpKey() {