From 10809cdd99be078eb30f87866977fdb1f49c15d2 Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Fri, 26 Mar 2010 12:47:06 +0100
Subject: [PATCH] Some love for the Cpaster plugin

- Put classes into namespace.
- Fix settings not storing the selected protocol.
- Refactor settings by introducing standard handling.
- Create PasteSelectDialog class and fix list/refresh handling.
- No longer stuff the QListWidget into the protocol for listing, wire
via signals.
---
 src/plugins/cpaster/codepasterprotocol.cpp    |  13 +-
 src/plugins/cpaster/codepasterprotocol.h      |   4 +-
 src/plugins/cpaster/cpaster.pro               |   8 +-
 src/plugins/cpaster/cpasterplugin.cpp         |  66 +++------
 src/plugins/cpaster/cpasterplugin.h           |   8 +-
 src/plugins/cpaster/pastebindotcaprotocol.cpp |   3 +-
 src/plugins/cpaster/pastebindotcaprotocol.h   |   2 +
 .../cpaster/pastebindotcomprotocol.cpp        |   2 +
 src/plugins/cpaster/pastebindotcomprotocol.h  |   3 +-
 .../cpaster/pastebindotcomsettings.cpp        |   2 +
 src/plugins/cpaster/pastebindotcomsettings.h  |   3 +-
 src/plugins/cpaster/pasteselectdialog.cpp     | 135 ++++++++++++++++++
 src/plugins/cpaster/pasteselectdialog.h       |  73 ++++++++++
 src/plugins/cpaster/protocol.cpp              |   6 +-
 src/plugins/cpaster/protocol.h                |  14 +-
 src/plugins/cpaster/settings.cpp              |  78 ++++++++++
 src/plugins/cpaster/settings.h                |  58 ++++++++
 src/plugins/cpaster/settingspage.cpp          | 114 +++++++--------
 src/plugins/cpaster/settingspage.h            |  42 +++---
 src/plugins/cpaster/settingspage.ui           |  18 +--
 20 files changed, 484 insertions(+), 168 deletions(-)
 create mode 100644 src/plugins/cpaster/pasteselectdialog.cpp
 create mode 100644 src/plugins/cpaster/pasteselectdialog.h
 create mode 100644 src/plugins/cpaster/settings.cpp
 create mode 100644 src/plugins/cpaster/settings.h

diff --git a/src/plugins/cpaster/codepasterprotocol.cpp b/src/plugins/cpaster/codepasterprotocol.cpp
index c9467e92cba..93fa3b77c51 100644
--- a/src/plugins/cpaster/codepasterprotocol.cpp
+++ b/src/plugins/cpaster/codepasterprotocol.cpp
@@ -57,7 +57,7 @@ CodePasterProtocol::~CodePasterProtocol()
 
 QString CodePasterProtocol::name() const
 {
-    return "CodePaster";
+    return QLatin1String("CodePaster");
 }
 
 bool CodePasterProtocol::canList() const
@@ -98,12 +98,11 @@ void CodePasterProtocol::fetch(const QString &id)
     fetchId = id;
 }
 
-void CodePasterProtocol::list(QListWidget *listWidget)
+void CodePasterProtocol::list()
 {
     QString hostName = m_page->hostName();
     if (!isValidHostName(hostName))
         return;
-    this->listWidget = listWidget;
     QString link = QLatin1String("http://");
     link += hostName;
     link += QLatin1String("/?command=browse&format=raw");
@@ -170,11 +169,9 @@ void CodePasterProtocol::listFinished()
     if (listReply->error()) {
         ICore::instance()->messageManager()->printToOutputPane(listReply->errorString(), true);
     } else {
-        QByteArray data = listReply->readAll();
-        listWidget->clear();
-        QStringList lines = QString(data).split(QLatin1Char('\n'));
-        listWidget->addItems(lines);
-        listWidget = 0;
+        const QByteArray data = listReply->readAll();
+        const QStringList lines = QString::fromAscii(data).split(QLatin1Char('\n'));
+        emit listDone(name(), lines);
     }
     listReply->deleteLater();
     listReply = 0;
diff --git a/src/plugins/cpaster/codepasterprotocol.h b/src/plugins/cpaster/codepasterprotocol.h
index 6a4ef01c119..af8f3a3d152 100644
--- a/src/plugins/cpaster/codepasterprotocol.h
+++ b/src/plugins/cpaster/codepasterprotocol.h
@@ -36,7 +36,6 @@
 #include <QtNetwork/QNetworkAccessManager>
 
 QT_BEGIN_NAMESPACE
-class QListWidget;
 class QNetworkReply;
 QT_END_NAMESPACE
 
@@ -58,7 +57,7 @@ public:
     Core::IOptionsPage *settingsPage();
 
     void fetch(const QString &id);
-    void list(QListWidget *listWidget);
+    void list();
     void paste(const QString &text,
                const QString &username = QString(),
                const QString &comment = QString(),
@@ -75,7 +74,6 @@ private:
     QNetworkAccessManager manager;
     QNetworkReply *reply;
     QNetworkReply *listReply;
-    QListWidget *listWidget;
     QString fetchId;
 };
 
diff --git a/src/plugins/cpaster/cpaster.pro b/src/plugins/cpaster/cpaster.pro
index d5d59b87dac..a705b1463b3 100644
--- a/src/plugins/cpaster/cpaster.pro
+++ b/src/plugins/cpaster/cpaster.pro
@@ -12,7 +12,9 @@ HEADERS += cpasterplugin.h \
     codepastersettings.h \
     pastebindotcomprotocol.h \
     pastebindotcomsettings.h \
-    pastebindotcaprotocol.h
+    pastebindotcaprotocol.h \
+    settings.h \
+    pasteselectdialog.h
 SOURCES += cpasterplugin.cpp \
     settingspage.cpp \
     protocol.cpp \
@@ -21,7 +23,9 @@ SOURCES += cpasterplugin.cpp \
     codepastersettings.cpp \
     pastebindotcomprotocol.cpp \
     pastebindotcomsettings.cpp \
-    pastebindotcaprotocol.cpp
+    pastebindotcaprotocol.cpp \
+    settings.cpp \
+    pasteselectdialog.cpp
 FORMS += settingspage.ui \
     pasteselect.ui \
     pasteview.ui \
diff --git a/src/plugins/cpaster/cpasterplugin.cpp b/src/plugins/cpaster/cpasterplugin.cpp
index d9e872d1f39..47bd48e7f20 100644
--- a/src/plugins/cpaster/cpasterplugin.cpp
+++ b/src/plugins/cpaster/cpasterplugin.cpp
@@ -29,14 +29,14 @@
 
 #include "cpasterplugin.h"
 
-#include "ui_pasteselect.h"
-
 #include "splitter.h"
 #include "pasteview.h"
 #include "codepasterprotocol.h"
 #include "pastebindotcomprotocol.h"
 #include "pastebindotcaprotocol.h"
+#include "pasteselectdialog.h"
 #include "settingspage.h"
+#include "settings.h"
 
 #include <coreplugin/actionmanager/actionmanager.h>
 #include <coreplugin/actionmanager/actioncontainer.h>
@@ -65,8 +65,7 @@ using namespace CodePaster;
 using namespace Core;
 using namespace TextEditor;
 
-CodepasterPlugin::CodepasterPlugin()
-    : m_settingsPage(0)
+CodepasterPlugin::CodepasterPlugin() : m_settings(new Settings)
 {
 }
 
@@ -85,8 +84,9 @@ bool CodepasterPlugin::initialize(const QStringList &arguments, QString *error_m
     globalcontext << UniqueIDManager::instance()->uniqueIdentifier(Core::Constants::C_GLOBAL);
 
     // Create the settings Page
-    m_settingsPage = new SettingsPage();
-    addAutoReleasedObject(m_settingsPage);
+    m_settings->fromSettings(Core::ICore::instance()->settings());
+    SettingsPage *settingsPage = new SettingsPage(m_settings);
+    addAutoReleasedObject(settingsPage);
 
     // Create the protocols and append them to the Settings
     Protocol *protos[] =  { new CodePasterProtocol(),
@@ -97,7 +97,7 @@ bool CodepasterPlugin::initialize(const QStringList &arguments, QString *error_m
         connect(protos[i], SIGNAL(pasteDone(QString)), this, SLOT(finishPost(QString)));
         connect(protos[i], SIGNAL(fetchDone(QString,QString,bool)),
                 this, SLOT(finishFetch(QString,QString,bool)));
-        m_settingsPage->addProtocol(protos[i]->name());
+        settingsPage->addProtocol(protos[i]->name());
         if (protos[i]->hasSettings())
             addAutoReleasedObject(protos[i]->settingsPage());
         m_protocols.append(protos[i]);
@@ -176,14 +176,14 @@ void CodepasterPlugin::post()
         data = textEditor->contents();
 
     FileDataList lst = splitDiffToFiles(data.toLatin1());
-    QString username = m_settingsPage->username();
+    QString username = m_settings->username;
     QString description;
     QString comment;
     QString protocolName;
 
     PasteView view(0);
     foreach (Protocol *p, m_protocols) {
-        view.addProtocol(p->name(), p->name() == m_settingsPage->defaultProtocol());
+        view.addProtocol(p->name(), p->name() == m_settings->protocol);
     }
 
     if (!view.show(username, description, comment, lst))
@@ -214,55 +214,23 @@ void CodepasterPlugin::post()
 
 void CodepasterPlugin::fetch()
 {
-    QDialog dialog(ICore::instance()->mainWindow());
-    Ui_PasteSelectDialog ui;
-    ui.setupUi(&dialog);
-    foreach(const Protocol *protocol, m_protocols)
-        ui.protocolBox->addItem(protocol->name());
-    ui.protocolBox->setCurrentIndex(ui.protocolBox->findText(m_settingsPage->defaultProtocol()));
-
-    ui.listWidget->addItems(QStringList() << tr("This protocol supports no listing"));
-    ui.listWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
-#ifndef Q_WS_MACX
-    ui.listWidget->setFrameStyle(QFrame::NoFrame);
-#endif // Q_WS_MACX
-    QFont listFont = ui.listWidget->font();
-    listFont.setFamily("Courier");
-    listFont.setStyleHint(QFont::TypeWriter);
-    ui.listWidget->setFont(listFont);
-    // ### TODO2: when we change the protocol, we need to relist
-    foreach(Protocol *protocol, m_protocols) {
-        if (protocol->name() == ui.protocolBox->currentText() && protocol->canList()) {
-            ui.listWidget->clear();
-            ui.listWidget->addItems(QStringList() << tr("Waiting for items"));
-            protocol->list(ui.listWidget);
-            break;
-        }
-    }
+    PasteSelectDialog dialog(m_protocols, ICore::instance()->mainWindow());
+    dialog.setProtocol(m_settings->protocol);
 
-    int result = dialog.exec();
-    if (!result)
+    if (dialog.exec() != QDialog::Accepted)
         return;
-    QStringList list = ui.pasteEdit->text().split(QLatin1Char(' '));
-    if (list.isEmpty())
+    const QString pasteID = dialog.pasteId();
+    if (pasteID.isEmpty())
         return;
-    QString pasteID = list.first();
-
-    // Get Protocol
-    foreach(Protocol *protocol, m_protocols) {
-        if (protocol->name() == ui.protocolBox->currentText()) {
-            protocol->fetch(pasteID);
-            break;
-        }
-    }
+    m_protocols[dialog.protocolIndex()]->fetch(pasteID);
 }
 
 void CodepasterPlugin::finishPost(const QString &link)
 {
-    if (m_settingsPage->copyToClipBoard())
+    if (m_settings->copyToClipboard)
         QApplication::clipboard()->setText(link);
     ICore::instance()->messageManager()->printToOutputPane(link,
-                                                           m_settingsPage->displayOutput());
+                                                           m_settings->displayOutput);
 }
 
 // Extract the characters that can be used for a file name from a title
diff --git a/src/plugins/cpaster/cpasterplugin.h b/src/plugins/cpaster/cpasterplugin.h
index 98e9b39ff1b..c07695c28aa 100644
--- a/src/plugins/cpaster/cpasterplugin.h
+++ b/src/plugins/cpaster/cpasterplugin.h
@@ -33,17 +33,17 @@
 #include <extensionsystem/iplugin.h>
 
 #include <QtCore/QStringList>
+#include <QtCore/QSharedPointer>
 
 QT_BEGIN_NAMESPACE
 class QAction;
 QT_END_NAMESPACE
 
-class Protocol;
-
 namespace CodePaster {
-class SettingsPage;
 class CustomFetcher;
 class CustomPoster;
+struct Settings;
+class Protocol;
 
 class CodepasterPlugin : public ExtensionSystem::IPlugin
 {
@@ -66,9 +66,9 @@ public slots:
                      bool error);
 
 private:
+    const QSharedPointer<Settings> m_settings;
     QAction *m_postAction;
     QAction *m_fetchAction;
-    SettingsPage *m_settingsPage;
     QList<Protocol*> m_protocols;
     QStringList m_fetchedSnippets;
 };
diff --git a/src/plugins/cpaster/pastebindotcaprotocol.cpp b/src/plugins/cpaster/pastebindotcaprotocol.cpp
index 36e2a527781..83b7e8e867f 100644
--- a/src/plugins/cpaster/pastebindotcaprotocol.cpp
+++ b/src/plugins/cpaster/pastebindotcaprotocol.cpp
@@ -33,7 +33,7 @@
 #include <QtNetwork/QNetworkReply>
 
 using namespace Core;
-
+namespace CodePaster {
 PasteBinDotCaProtocol::PasteBinDotCaProtocol()
 {
     connect(&http, SIGNAL(requestFinished(int,bool)),
@@ -101,3 +101,4 @@ void PasteBinDotCaProtocol::fetchFinished()
     reply = 0;
     emit fetchDone(title, content, error);
 }
+} // namespace CodePaster
diff --git a/src/plugins/cpaster/pastebindotcaprotocol.h b/src/plugins/cpaster/pastebindotcaprotocol.h
index 813a6fe30af..7cea5d21253 100644
--- a/src/plugins/cpaster/pastebindotcaprotocol.h
+++ b/src/plugins/cpaster/pastebindotcaprotocol.h
@@ -35,6 +35,7 @@
 #include <QtNetwork/QNetworkAccessManager>
 #include <QtNetwork/QHttp>
 
+namespace CodePaster {
 class PasteBinDotCaProtocol : public Protocol
 {
     Q_OBJECT
@@ -64,4 +65,5 @@ private:
     int postId;
 };
 
+} // namespace CodePaster
 #endif // PASTEBINDOTCAPROTOCOL_H
diff --git a/src/plugins/cpaster/pastebindotcomprotocol.cpp b/src/plugins/cpaster/pastebindotcomprotocol.cpp
index 2f5a3fa5b91..7a365529930 100644
--- a/src/plugins/cpaster/pastebindotcomprotocol.cpp
+++ b/src/plugins/cpaster/pastebindotcomprotocol.cpp
@@ -36,6 +36,7 @@
 
 using namespace Core;
 
+namespace CodePaster {
 PasteBinDotComProtocol::PasteBinDotComProtocol()
 {
     settings = new PasteBinDotComSettings();
@@ -127,3 +128,4 @@ Core::IOptionsPage* PasteBinDotComProtocol::settingsPage()
 {
     return settings;
 }
+} // namespace CodePaster
diff --git a/src/plugins/cpaster/pastebindotcomprotocol.h b/src/plugins/cpaster/pastebindotcomprotocol.h
index ae6a021d089..edb2b319cfc 100644
--- a/src/plugins/cpaster/pastebindotcomprotocol.h
+++ b/src/plugins/cpaster/pastebindotcomprotocol.h
@@ -35,6 +35,7 @@
 #include <QtNetwork/QNetworkAccessManager>
 #include <QtNetwork/QHttp>
 
+namespace CodePaster {
 class PasteBinDotComSettings;
 
 class PasteBinDotComProtocol : public Protocol
@@ -70,5 +71,5 @@ private:
     QHttp http;
     int postId;
 };
-
+} // namespace CodePaster
 #endif // PASTEBINDOTCOMPROTOCOL_H
diff --git a/src/plugins/cpaster/pastebindotcomsettings.cpp b/src/plugins/cpaster/pastebindotcomsettings.cpp
index f4649f5eb71..68adfd9f970 100644
--- a/src/plugins/cpaster/pastebindotcomsettings.cpp
+++ b/src/plugins/cpaster/pastebindotcomsettings.cpp
@@ -35,6 +35,7 @@
 #include <QtCore/QSettings>
 #include <QtCore/QCoreApplication>
 
+namespace CodePaster {
 PasteBinDotComSettings::PasteBinDotComSettings()
 {
     m_settings = Core::ICore::instance()->settings();
@@ -94,3 +95,4 @@ QString PasteBinDotComSettings::hostPrefix() const
 {
     return m_hostPrefix;
 }
+} //namespace CodePaster
diff --git a/src/plugins/cpaster/pastebindotcomsettings.h b/src/plugins/cpaster/pastebindotcomsettings.h
index 6c6b77331b7..ec1fe9bdeb1 100644
--- a/src/plugins/cpaster/pastebindotcomsettings.h
+++ b/src/plugins/cpaster/pastebindotcomsettings.h
@@ -40,6 +40,7 @@ QT_BEGIN_NAMESPACE
 class QSettings;
 QT_END_NAMESPACE
 
+namespace CodePaster {
 class PasteBinDotComSettings : public Core::IOptionsPage
 {
     Q_OBJECT
@@ -64,5 +65,5 @@ private:
     QSettings *m_settings;
     QString m_hostPrefix;
 };
-
+} // namespace CodePaster
 #endif
diff --git a/src/plugins/cpaster/pasteselectdialog.cpp b/src/plugins/cpaster/pasteselectdialog.cpp
new file mode 100644
index 00000000000..06358e0409b
--- /dev/null
+++ b/src/plugins/cpaster/pasteselectdialog.cpp
@@ -0,0 +1,135 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "pasteselectdialog.h"
+#include "protocol.h"
+
+#include <utils/qtcassert.h>
+
+#include <QtCore/QDebug>
+#include <QtGui/QPushButton>
+
+namespace CodePaster {
+
+PasteSelectDialog::PasteSelectDialog(const QList<Protocol*> &protocols,
+                                     QWidget *parent) :
+    QDialog(parent),
+    m_protocols(protocols)
+{
+    m_ui.setupUi(this);
+    foreach(const Protocol *protocol, protocols) {
+        m_ui.protocolBox->addItem(protocol->name());
+        connect(protocol, SIGNAL(listDone(QString,QStringList)),
+                this, SLOT(listDone(QString,QStringList)));
+    }
+    connect(m_ui.protocolBox, SIGNAL(currentIndexChanged(int)),
+            this, SLOT(protocolChanged(int)));
+
+    m_refreshButton = m_ui.buttons->addButton(tr("Refresh"), QDialogButtonBox::ActionRole);
+    connect(m_refreshButton, SIGNAL(clicked()), this, SLOT(list()));
+
+    m_ui.listWidget->setSelectionMode(QAbstractItemView::SingleSelection);
+#ifndef Q_WS_MACX
+    m_ui.listWidget->setFrameStyle(QFrame::NoFrame);
+#endif // Q_WS_MACX
+    // Proportional formatting of columns for CodePaster
+    QFont listFont = m_ui.listWidget->font();
+    listFont.setFamily(QLatin1String("Courier"));
+    listFont.setStyleHint(QFont::TypeWriter);
+    m_ui.listWidget->setFont(listFont);
+}
+
+PasteSelectDialog::~PasteSelectDialog()
+{
+}
+
+QString PasteSelectDialog::pasteId() const
+{
+    QString id = m_ui.pasteEdit->text();
+    const int blankPos = id.indexOf(QLatin1Char(' '));
+    if (blankPos != -1)
+        id.truncate(blankPos);
+    return id;
+}
+
+void PasteSelectDialog::setProtocol(const QString &p)
+{
+    const int index = m_ui.protocolBox->findText(p);
+    if (index >= 0) {
+        if (index != m_ui.protocolBox->currentIndex()) {
+            m_ui.protocolBox->setCurrentIndex(index);
+        } else {
+            // Trigger a refresh
+            protocolChanged(index);
+        }
+    }
+}
+
+QString PasteSelectDialog::protocol() const
+{
+    return m_ui.protocolBox->currentText();
+}
+
+int PasteSelectDialog::protocolIndex() const
+{
+    return m_ui.protocolBox->currentIndex();
+}
+
+void PasteSelectDialog::listDone(const QString &name, const QStringList &items)
+{
+    // Set if the protocol is still current
+    if (name == protocol()) {
+        m_ui.listWidget->clear();
+        m_ui.listWidget->addItems(items);
+    }
+}
+
+void PasteSelectDialog::list()
+{
+    const int index = protocolIndex();
+
+    QTC_ASSERT(m_protocols.at(index)->canList(), return);
+
+    m_ui.listWidget->clear();
+    m_ui.listWidget->addItem(new QListWidgetItem(tr("Waiting for items")));
+    m_protocols[index]->list();
+}
+
+void PasteSelectDialog::protocolChanged(int i)
+{
+    const bool canList = m_protocols.at(i)->canList();
+    m_refreshButton->setEnabled(canList);
+    if (canList) {
+        list();
+    } else {
+        m_ui.listWidget->clear();
+        m_ui.listWidget->addItem(new QListWidgetItem(tr("This protocol does not support listing")));
+    }
+}
+} // namespace CodePaster
diff --git a/src/plugins/cpaster/pasteselectdialog.h b/src/plugins/cpaster/pasteselectdialog.h
new file mode 100644
index 00000000000..f9c0b34286f
--- /dev/null
+++ b/src/plugins/cpaster/pasteselectdialog.h
@@ -0,0 +1,73 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PASTESELECTDIALOG_H
+#define PASTESELECTDIALOG_H
+
+#include "ui_pasteselect.h"
+
+#include <QtCore/QList>
+
+QT_FORWARD_DECLARE_CLASS(QPushButton)
+
+namespace CodePaster {
+class Protocol;
+
+class PasteSelectDialog : public QDialog
+{
+    Q_OBJECT
+public:
+    explicit PasteSelectDialog(const QList<Protocol*> &protocols,
+                               QWidget *parent = 0);
+    ~PasteSelectDialog();
+
+    QString pasteId() const;
+
+    QString protocol() const;
+    void setProtocol(const QString &);
+
+    int protocolIndex() const;
+
+signals:
+
+private slots:
+    void protocolChanged(int);
+    void list();
+    void listDone(const QString &name, const QStringList &items);
+
+private:
+    const QList<Protocol*> m_protocols;
+
+    Ui_PasteSelectDialog m_ui;
+    QPushButton *m_refreshButton;
+};
+
+} // namespace CodePaster
+
+#endif // PASTESELECTDIALOG_H
diff --git a/src/plugins/cpaster/protocol.cpp b/src/plugins/cpaster/protocol.cpp
index 33205dd4a9c..ffec7caa73e 100644
--- a/src/plugins/cpaster/protocol.cpp
+++ b/src/plugins/cpaster/protocol.cpp
@@ -28,7 +28,7 @@
 **************************************************************************/
 #include "protocol.h"
 
-#include <QtCore/qglobal.h>
+namespace CodePaster {
 
 Protocol::Protocol()
         : QObject()
@@ -59,7 +59,9 @@ Core::IOptionsPage* Protocol::settingsPage()
     return 0;
 }
 
-void Protocol::list(QListWidget*)
+void Protocol::list()
 {
     qFatal("Base Protocol list() called");
 }
+
+} //namespace CodePaster
diff --git a/src/plugins/cpaster/protocol.h b/src/plugins/cpaster/protocol.h
index 21066fd77e6..d8d9de3827f 100644
--- a/src/plugins/cpaster/protocol.h
+++ b/src/plugins/cpaster/protocol.h
@@ -30,12 +30,13 @@
 #ifndef PROTOCOL_H
 #define PROTOCOL_H
 
-#include <coreplugin/dialogs/ioptionspage.h>
+#include <QtCore/QObject>
 
-QT_BEGIN_NAMESPACE
-class QListWidget;
-QT_END_NAMESPACE
+namespace Core {
+    class IOptionsPage;
+}
 
+namespace CodePaster {
 class Protocol : public QObject
 {
     Q_OBJECT
@@ -52,7 +53,7 @@ public:
     virtual Core::IOptionsPage* settingsPage();
 
     virtual void fetch(const QString &id) = 0;
-    virtual void list(QListWidget *listWidget);
+    virtual void list();
     virtual void paste(const QString &text,
                        const QString &username = QString(),
                        const QString &comment = QString(),
@@ -63,6 +64,9 @@ signals:
     void fetchDone(const QString &titleDescription,
                    const QString &content,
                    bool error);
+    void listDone(const QString &name, const QStringList &result);
 };
 
+} //namespace CodePaster
+
 #endif // PROTOCOL_H
diff --git a/src/plugins/cpaster/settings.cpp b/src/plugins/cpaster/settings.cpp
new file mode 100644
index 00000000000..8ca8cdd05e0
--- /dev/null
+++ b/src/plugins/cpaster/settings.cpp
@@ -0,0 +1,78 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "settings.h"
+
+#include <QtCore/QVariant>
+#include <QtCore/QSettings>
+
+static const char groupC[] = "CodePaster";
+static const char userNameKeyC[] = "UserName";
+static const char defaultProtocolKeyC[] = "DefaultProtocol";
+static const char copyToClipboardKeyC[] = "CopyToClipboard";
+static const char displayOutputKeyC[] = "DisplayOutput";
+static const char defaultProtocolC[] = "CodePaster";
+
+namespace CodePaster {
+
+Settings::Settings() : copyToClipboard(true), displayOutput(true)
+{
+}
+
+bool Settings::equals(const Settings &rhs) const
+{
+    return copyToClipboard == rhs.copyToClipboard && displayOutput == rhs.displayOutput
+            && username == rhs.username && protocol == rhs.protocol;
+}
+
+void Settings::toSettings(QSettings *settings) const
+{
+    settings->beginGroup(QLatin1String(groupC));
+    settings->setValue(QLatin1String(userNameKeyC), username);
+    settings->setValue(QLatin1String(defaultProtocolKeyC), protocol);
+    settings->setValue(QLatin1String(copyToClipboardKeyC), copyToClipboard);
+    settings->setValue(QLatin1String(displayOutputKeyC), displayOutput);
+    settings->endGroup();
+}
+
+void Settings::fromSettings(const QSettings *settings)
+{
+    const QString rootKey = QLatin1String(groupC) + QLatin1Char('/');
+#ifdef Q_OS_WIN
+    const QString defaultUser = qgetenv("USERNAME");
+#else
+    const QString defaultUser = qgetenv("USER");
+#endif
+    username = settings->value(rootKey + QLatin1String(userNameKeyC), defaultUser).toString();
+    protocol = settings->value(rootKey + QLatin1String(defaultProtocolKeyC), QLatin1String(defaultProtocolC)).toString();
+    copyToClipboard = settings->value(rootKey + QLatin1String(copyToClipboardKeyC), true).toBool();
+    displayOutput = settings->value(rootKey + QLatin1String(displayOutputKeyC), true).toBool();
+}
+
+} // namespace CodePaster
diff --git a/src/plugins/cpaster/settings.h b/src/plugins/cpaster/settings.h
new file mode 100644
index 00000000000..c199089b7aa
--- /dev/null
+++ b/src/plugins/cpaster/settings.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SETTINGS_H
+#define SETTINGS_H
+
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+class QSettings;
+QT_END_NAMESPACE
+
+namespace CodePaster {
+
+struct Settings {
+    Settings();
+    void toSettings(QSettings *s) const;
+    void fromSettings(const QSettings *s);
+    bool equals(const Settings &s) const;
+
+    QString username;
+    QString protocol;
+    bool copyToClipboard;
+    bool displayOutput;
+};
+
+inline bool operator==(const Settings &s1, const Settings &s2) { return s1.equals(s2); }
+inline bool operator!=(const Settings &s1, const Settings &s2) { return !s1.equals(s2); }
+
+} // namespace CodePaster
+
+#endif // SETTINGS_H
diff --git a/src/plugins/cpaster/settingspage.cpp b/src/plugins/cpaster/settingspage.cpp
index ec44386684e..708e4662c18 100644
--- a/src/plugins/cpaster/settingspage.cpp
+++ b/src/plugins/cpaster/settingspage.cpp
@@ -28,37 +28,60 @@
 **************************************************************************/
 
 #include "settingspage.h"
+#include "settings.h"
 #include "cpasterconstants.h"
 
+#include <utils/qtcassert.h>
 #include <coreplugin/icore.h>
 
-#include <QtGui/QLineEdit>
-#include <QtGui/QFileDialog>
-
-#include <QtCore/QDebug>
-#include <QtCore/QVariant>
 #include <QtCore/QSettings>
 #include <QtCore/QTextStream>
 #include <QtCore/QCoreApplication>
 
-using namespace CodePaster;
+namespace CodePaster {
 
-SettingsPage::SettingsPage()
+SettingsWidget::SettingsWidget(const QStringList &protocols, QWidget *parent) :
+    QWidget(parent)
+{
+    m_ui.setupUi(this);
+    m_ui.defaultProtocol->addItems(protocols);
+}
+
+QString SettingsWidget::searchKeywords() const
+{
+    QString rc;
+    QTextStream(&rc) << m_ui.protocolLabel->text() << ' '
+            << m_ui.userNameLabel->text();
+    rc.remove(QLatin1Char('&'));
+    return rc;
+}
+
+void SettingsWidget::setSettings(const Settings &settings)
+{
+    m_ui.userEdit->setText(settings.username);
+    const int index = m_ui.defaultProtocol->findText(settings.protocol);
+    m_ui.defaultProtocol->setCurrentIndex(index == -1 ? 0  : index);
+    m_ui.clipboardBox->setChecked(settings.copyToClipboard);
+    m_ui.displayBox->setChecked(settings.displayOutput);
+}
+
+Settings SettingsWidget::settings()
+{
+    Settings rc;
+    rc.username = m_ui.userEdit->text();
+    rc.protocol = m_ui.defaultProtocol->currentText();
+    rc.copyToClipboard = m_ui.clipboardBox->isChecked();
+    rc.displayOutput = m_ui.displayBox->isChecked();
+    return rc;
+}
+
+SettingsPage::SettingsPage(const QSharedPointer<Settings> &settings) :
+    m_settings(settings)
+{
+}
+
+SettingsPage::~SettingsPage()
 {
-    m_settings = Core::ICore::instance()->settings();
-    if (m_settings) {
-        m_settings->beginGroup("CodePaster");
-#ifdef Q_OS_WIN32
-        QString defaultUser = qgetenv("USERNAME");
-#else
-        QString defaultUser = qgetenv("USER");
-#endif
-        m_username = m_settings->value("UserName", defaultUser).toString();
-        m_protocol = m_settings->value("DefaultProtocol", "CodePaster").toString();
-        m_copy = m_settings->value("CopyToClipboard", true).toBool();
-        m_output = m_settings->value("DisplayOutput", true).toBool();
-        m_settings->endGroup();
-    }
 }
 
 QString SettingsPage::id() const
@@ -83,37 +106,22 @@ QString SettingsPage::displayCategory() const
 
 QWidget *SettingsPage::createPage(QWidget *parent)
 {
-    QWidget *w = new QWidget(parent);
-    m_ui.setupUi(w);
-    m_ui.defaultProtocol->clear();
-    m_ui.defaultProtocol->insertItems(0, m_protocols);
-    m_ui.userEdit->setText(m_username);
-    m_ui.clipboardBox->setChecked(m_copy);
-    m_ui.displayBox->setChecked(m_output);
-    if (m_searchKeywords.isEmpty()) {
-        QTextStream(&m_searchKeywords) << m_ui.protocolLabel->text() << ' '
-                << m_ui.userNameLabel->text();
-        m_searchKeywords.remove(QLatin1Char('&'));
-    }
-    return w;
+    m_widget = new SettingsWidget(m_protocols, parent);
+    m_widget->setSettings(*m_settings);
+
+    if (m_searchKeywords.isEmpty())
+        m_searchKeywords = m_widget->searchKeywords();
+    return m_widget;
 }
 
 void SettingsPage::apply()
 {
-    m_username = m_ui.userEdit->text();
-    m_protocol = m_ui.defaultProtocol->currentText();
-    m_copy = m_ui.clipboardBox->isChecked();
-    m_output = m_ui.displayBox->isChecked();
-
-    if (!m_settings)
-        return;
-
-    m_settings->beginGroup("CodePaster");
-    m_settings->setValue("UserName", m_username);
-    m_settings->setValue("DefaultProtocol", m_protocol);
-    m_settings->setValue("CopyToClipboard", m_copy);
-    m_settings->setValue("DisplayOutput", m_output);
-    m_settings->endGroup();
+    QTC_ASSERT(m_widget, return)
+    const Settings newSettings = m_widget->settings();
+    if (newSettings != *m_settings) {
+        *m_settings = newSettings;
+        m_settings->toSettings(Core::ICore::instance()->settings());
+    }
 }
 
 bool SettingsPage::matches(const QString &s) const
@@ -126,12 +134,4 @@ void SettingsPage::addProtocol(const QString &name)
     m_protocols.append(name);
 }
 
-QString SettingsPage::username() const
-{
-    return m_username;
-}
-
-QString SettingsPage::defaultProtocol() const
-{
-    return m_protocol;
-}
+} // namespace CodePaster
diff --git a/src/plugins/cpaster/settingspage.h b/src/plugins/cpaster/settingspage.h
index 834c4ef2666..063c372afac 100644
--- a/src/plugins/cpaster/settingspage.h
+++ b/src/plugins/cpaster/settingspage.h
@@ -35,19 +35,34 @@
 #include <coreplugin/dialogs/ioptionspage.h>
 
 #include <QtCore/QStringList>
-
-QT_BEGIN_NAMESPACE
-class QSettings;
-QT_END_NAMESPACE
+#include <QtCore/QSharedPointer>
+#include <QtCore/QPointer>
 
 namespace CodePaster {
 
+struct Settings;
+
+class SettingsWidget : public QWidget {
+    Q_OBJECT
+public:
+    explicit SettingsWidget(const QStringList &protocols, QWidget *parent = 0);
+
+    void setSettings(const Settings &);
+    Settings settings();
+
+    QString searchKeywords() const;
+
+private:
+    Ui_SettingsPage m_ui;
+};
+
 class SettingsPage : public Core::IOptionsPage
 {
     Q_OBJECT
-
+    Q_DISABLE_COPY(SettingsPage)
 public:
-    SettingsPage();
+    explicit SettingsPage(const QSharedPointer<Settings> &settings);
+    virtual ~SettingsPage();
 
     QString id() const;
     QString displayName() const;
@@ -60,22 +75,13 @@ public:
     virtual bool matches(const QString &) const;
 
     void addProtocol(const QString& name);
-    QString username() const;
-    QString defaultProtocol() const;
-
-    inline bool copyToClipBoard() const { return m_copy; }
-    inline bool displayOutput() const { return m_output; }
 
 private:
-    Ui_SettingsPage m_ui;
-    QSettings *m_settings;
+    const QSharedPointer<Settings> m_settings;
 
-    QString m_searchKeywords;
+    QPointer<SettingsWidget> m_widget;
     QStringList m_protocols;
-    QString m_username;
-    QString m_protocol;
-    bool m_copy;
-    bool m_output;
+    QString m_searchKeywords;
 };
 
 } // namespace CodePaster
diff --git a/src/plugins/cpaster/settingspage.ui b/src/plugins/cpaster/settingspage.ui
index aab35a272ab..8284013ae44 100644
--- a/src/plugins/cpaster/settingspage.ui
+++ b/src/plugins/cpaster/settingspage.ui
@@ -20,23 +20,7 @@
        </widget>
       </item>
       <item row="0" column="1">
-       <widget class="QComboBox" name="defaultProtocol">
-        <item>
-         <property name="text">
-          <string>CodePaster</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>Pastebin.ca</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>Pastebin.com</string>
-         </property>
-        </item>
-       </widget>
+       <widget class="QComboBox" name="defaultProtocol"/>
       </item>
       <item row="1" column="0">
        <widget class="QLabel" name="userNameLabel">
-- 
GitLab