remotedesktopsmodel.cpp 8.87 KB
Newer Older
1 2 3
/****************************************************************************
**
** Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org>
4
** Copyright (C) 2009 Tony Murray <murraytony@gmail.com>
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
**
** This file is part of KDE.
**
** 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.
**
** You should have received a copy of the GNU General Public License
** along with this program; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA.
**
****************************************************************************/

#include "remotedesktopsmodel.h"
Tony Murray's avatar
Tony Murray committed
26
#include "bookmarkmanager.h"
27 28 29

#include <KStandardDirs>
#include <KDebug>
30
#include <KLocale>
31

32
RemoteDesktopsModel::RemoteDesktopsModel(QObject *parent)
Tony Murray's avatar
Tony Murray committed
33
        : QAbstractTableModel(parent)
34
{
Urs Wolfer's avatar
Urs Wolfer committed
35
    const QString file = KStandardDirs::locateLocal("data", "krdc/bookmarks.xml");
36 37
    m_manager = KBookmarkManager::managerForFile(file, "krdc");
    m_manager->setUpdate(true);
38
    connect(m_manager, SIGNAL(changed(const QString &, const QString &)), SLOT(bookmarksChanged()));
Tony Murray's avatar
Tony Murray committed
39
    buildModelFromBookmarkGroup(m_manager->root());
40

41 42 43
#ifdef BUILD_ZEROCONF
    // Add RDP and NX if they start announcing via Zeroconf:
    m_protocols["_rfb._tcp"] = "vnc";
44

45 46 47
    zeroconfBrowser = new DNSSD::ServiceBrowser("_rfb._tcp", true);
    connect(zeroconfBrowser, SIGNAL(finished()), this, SLOT(servicesChanged()));
    zeroconfBrowser->startBrowse();
Tony Murray's avatar
Tony Murray committed
48
    kDebug(5010) << "Browsing for zeroconf hosts.";
49
#endif
50 51 52 53 54 55
}

RemoteDesktopsModel::~RemoteDesktopsModel()
{
}

Tony Murray's avatar
Tony Murray committed
56
int RemoteDesktopsModel::columnCount(const QModelIndex &) const
57
{
Tony Murray's avatar
Tony Murray committed
58 59
    return 4;  // same as count of RemoteDesktopsModel::DisplayItems enum
}
Tony Murray's avatar
Tony Murray committed
60

Tony Murray's avatar
Tony Murray committed
61 62 63
int RemoteDesktopsModel::rowCount(const QModelIndex &) const
{
    return remoteDesktops.size();
64 65
}

Tony Murray's avatar
Tony Murray committed
66
Qt::ItemFlags RemoteDesktopsModel::flags(const QModelIndex &index) const
67
{
Tony Murray's avatar
Tony Murray committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
    if (!index.isValid())
        return 0;
    if (index.column() == RemoteDesktopsModel::Favorite) {
        return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
    }
    return Qt::ItemIsEnabled;
}

bool RemoteDesktopsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.isValid() && role == Qt::CheckStateRole && index.column() == RemoteDesktopsModel::Favorite) {
        bool checked = (Qt::CheckState)value.toUInt() == Qt::Checked;
        remoteDesktops[index.row()].favorite = checked;

        RemoteDesktop rd = remoteDesktops.at(index.row());
        if (checked) {
            KBookmarkGroup root = m_manager->root();
            root.addBookmark(rd.title, rd.url);
            m_manager->emitChanged(root);
        } else {
            BookmarkManager::removeByUrl(m_manager, rd.url, true, rd.title);
        }
        return true;
    }
    return false;
93 94 95 96 97 98 99
}

QVariant RemoteDesktopsModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

Tony Murray's avatar
Tony Murray committed
100
    RemoteDesktop item = remoteDesktops.at(index.row());
101

102 103
    switch (role) {
    case Qt::DisplayRole:
Tony Murray's avatar
Tony Murray committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
        switch (index.column()) {
        case RemoteDesktopsModel::Favorite:
            return item.favorite;
        case RemoteDesktopsModel::Title:
            return item.title;
        case RemoteDesktopsModel::LastConnected:
            return QVariant(item.lastConnected.dateTime());
        case RemoteDesktopsModel::Source:
            switch (item.source) {
            case RemoteDesktop::Bookmarks:
                return i18nc("Where each displayed link comes from", "Bookmarks");
            case RemoteDesktop::History:
                return i18nc("Where each displayed link comes from", "History");
            case RemoteDesktop::Zeroconf:
                return i18nc("Where each displayed link comes from", "Zeroconf");
            case RemoteDesktop::None:
                return i18nc("Where each displayed link comes from", "None");
            }
        default:
            return QVariant();
        }
    case Qt::CheckStateRole:
        if (index.column() == RemoteDesktopsModel::Favorite)
            return item.favorite ? Qt::Checked : Qt::Unchecked;
        return QVariant();
129
    case Qt::ToolTipRole:
Tony Murray's avatar
Tony Murray committed
130 131 132
        if (index.column() == RemoteDesktopsModel::LastConnected && !item.lastConnected.isNull())
            return KGlobal::locale()->formatDateTime(item.lastConnected.toLocalZone(), KLocale::FancyLongDate);
        return item.url;  //use the url for the tooltip
133
    case 10001: //url for dockwidget
Tony Murray's avatar
Tony Murray committed
134
        return item.url;
135
    case 10002: //filter
Tony Murray's avatar
Tony Murray committed
136
        return item.url + item.title; // return both uservisible and data
137 138 139
    default:
        return QVariant();
    }
140 141 142
}

QVariant RemoteDesktopsModel::headerData(int section, Qt::Orientation orientation,
Tony Murray's avatar
Tony Murray committed
143
        int role) const
144
{
Tony Murray's avatar
Tony Murray committed
145 146 147 148 149 150 151 152 153 154 155 156
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
        switch (section) {
        case RemoteDesktopsModel::Favorite:
            return QVariant(); // the favorite column is to small for a header
        case RemoteDesktopsModel::Title:
            return i18nc("Header of the connections list", "Remote Desktop");
        case RemoteDesktopsModel::LastConnected:
            return i18nc("Header of the connections list", "Last Connected");
        case RemoteDesktopsModel::Source:
            return i18nc("Header of the connections list", "Source");
        }
    }
157 158 159
    return QVariant();
}

Tony Murray's avatar
Tony Murray committed
160 161
// does not trigger view update, you must do this by hand after using this function
void RemoteDesktopsModel::removeAllItemsFromSources(RemoteDesktop::Sources sources)
162
{
Tony Murray's avatar
Tony Murray committed
163 164 165 166 167 168 169
    QMutableListIterator<RemoteDesktop> iter(remoteDesktops);
    while (iter.hasNext()) {
        iter.next();
        // if it matches any of the specified sources, remove it
        if ((iter.value().source & sources) > 0)
            iter.remove();
    }
170 171
}

Tony Murray's avatar
Tony Murray committed
172
void RemoteDesktopsModel::bookmarksChanged()
173
{
Tony Murray's avatar
Tony Murray committed
174 175 176 177
    kDebug(5010);
    removeAllItemsFromSources(RemoteDesktop::Bookmarks | RemoteDesktop::History);
    buildModelFromBookmarkGroup(m_manager->root());
    reset();
178 179
}

Tony Murray's avatar
Tony Murray committed
180
void RemoteDesktopsModel::buildModelFromBookmarkGroup(const KBookmarkGroup &group)
181 182 183
{
    KBookmark bm = group.first();
    while (!bm.isNull()) {
Tony Murray's avatar
Tony Murray committed
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
        if (bm.isGroup()) {
            // recurse subfolders and treat it special if it is the history folder
            buildModelFromBookmarkGroup(bm.toGroup());
        } else { // not a group

            RemoteDesktop item;
            item.title = bm.text();
            item.url = bm.url().url();
            int index = remoteDesktops.indexOf(item);
            bool newItem = index < 0;

            // we want to merge all copies of a url into one link, so if the item exists, update it
            if (group.metaDataItem("krdc-history") == "historyfolder") {
                KDateTime connected = KDateTime();
                bool ok = false;
                connected.setTime_t(bm.metaDataItem("time_visited").toLongLong(&ok));
                if (ok) {
                    (newItem ? item : remoteDesktops[index]).lastConnected = connected;
                }

                item.source = RemoteDesktop::History;
                item.favorite = false;
            } else {
                if (newItem) {
                    item.lastConnected = KDateTime();
                    item.favorite = true;
                    item.source = RemoteDesktop::Bookmarks;
                } else {
                    remoteDesktops[index].title = bm.text();
                    remoteDesktops[index].favorite = true;
                    remoteDesktops[index].source = RemoteDesktop::Bookmarks; // Bookmarks trump other types
                }
            }
            if (newItem)
                remoteDesktops.append(item);
        }
        bm = group.next(bm); // next item in the group
221 222 223
    }
}

224
#ifdef BUILD_ZEROCONF
Tony Murray's avatar
Tony Murray committed
225 226 227
void RemoteDesktopsModel::servicesChanged()
{
    //redo list because it is easier than finding and removing one that disappeared
228 229
    QList<DNSSD::RemoteService::Ptr> services = zeroconfBrowser->services();
    KUrl url;
Tony Murray's avatar
Tony Murray committed
230
    removeAllItemsFromSources(RemoteDesktop::Zeroconf);
231 232 233 234
    foreach(DNSSD::RemoteService::Ptr service, services) {
        url.setProtocol(m_protocols[service->type()].toLower());
        url.setHost(service->hostName());
        url.setPort(service->port());
235

Tony Murray's avatar
Tony Murray committed
236 237
        RemoteDesktop item;
        item.url = url.url();
238

Tony Murray's avatar
Tony Murray committed
239 240 241 242 243
        if (!remoteDesktops.contains(item)) {
            item.title = service->serviceName();
            item.source = RemoteDesktop::Zeroconf;
            item.favorite = false;
            remoteDesktops.append(item);
244 245
        }
    }
Tony Murray's avatar
Tony Murray committed
246
    reset();
247 248 249
}
#endif

250
#include "remotedesktopsmodel.moc"