remotedesktopsmodel.cpp 9.32 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
        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();
        }
125

Tony Murray's avatar
Tony Murray committed
126 127 128 129
    case Qt::CheckStateRole:
        if (index.column() == RemoteDesktopsModel::Favorite)
            return item.favorite ? Qt::Checked : Qt::Unchecked;
        return QVariant();
130

131
    case Qt::ToolTipRole:
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
        switch(index.column()) {
        case RemoteDesktopsModel::Favorite:
            if (item.favorite) {
                return i18nc("Remove the selected url from the bookarks menu", "Remove the bookmark for %1.", item.title);
            } else {
                return i18nc("Add the selected url to the bookmarks menu", "Bookmark %1.", item.title);
            }
        case RemoteDesktopsModel::LastConnected:
            if (!item.lastConnected.isNull()) {
                return KGlobal::locale()->formatDateTime(item.lastConnected.toLocalZone(), KLocale::FancyLongDate);
            }  // else fall through to default
        default:
            return item.url;  //use the url for the tooltip
        }

147
    case 10001: //url for dockwidget
Tony Murray's avatar
Tony Murray committed
148
        return item.url;
149

150
    case 10002: //filter
Tony Murray's avatar
Tony Murray committed
151
        return item.url + item.title; // return both uservisible and data
152

153 154 155
    default:
        return QVariant();
    }
156 157 158
}

QVariant RemoteDesktopsModel::headerData(int section, Qt::Orientation orientation,
Tony Murray's avatar
Tony Murray committed
159
        int role) const
160
{
Tony Murray's avatar
Tony Murray committed
161 162 163 164 165 166 167 168 169 170 171 172
    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");
        }
    }
173 174 175
    return QVariant();
}

Tony Murray's avatar
Tony Murray committed
176 177
// does not trigger view update, you must do this by hand after using this function
void RemoteDesktopsModel::removeAllItemsFromSources(RemoteDesktop::Sources sources)
178
{
Tony Murray's avatar
Tony Murray committed
179 180 181 182 183 184 185
    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();
    }
186 187
}

Tony Murray's avatar
Tony Murray committed
188
void RemoteDesktopsModel::bookmarksChanged()
189
{
Tony Murray's avatar
Tony Murray committed
190 191 192 193
    kDebug(5010);
    removeAllItemsFromSources(RemoteDesktop::Bookmarks | RemoteDesktop::History);
    buildModelFromBookmarkGroup(m_manager->root());
    reset();
194 195
}

Tony Murray's avatar
Tony Murray committed
196
void RemoteDesktopsModel::buildModelFromBookmarkGroup(const KBookmarkGroup &group)
197 198 199
{
    KBookmark bm = group.first();
    while (!bm.isNull()) {
Tony Murray's avatar
Tony Murray committed
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
        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
237 238 239
    }
}

240
#ifdef BUILD_ZEROCONF
Tony Murray's avatar
Tony Murray committed
241 242 243
void RemoteDesktopsModel::servicesChanged()
{
    //redo list because it is easier than finding and removing one that disappeared
244 245
    QList<DNSSD::RemoteService::Ptr> services = zeroconfBrowser->services();
    KUrl url;
Tony Murray's avatar
Tony Murray committed
246
    removeAllItemsFromSources(RemoteDesktop::Zeroconf);
247 248 249 250
    foreach(DNSSD::RemoteService::Ptr service, services) {
        url.setProtocol(m_protocols[service->type()].toLower());
        url.setHost(service->hostName());
        url.setPort(service->port());
251

Tony Murray's avatar
Tony Murray committed
252 253
        RemoteDesktop item;
        item.url = url.url();
254

Tony Murray's avatar
Tony Murray committed
255 256 257 258 259
        if (!remoteDesktops.contains(item)) {
            item.title = service->serviceName();
            item.source = RemoteDesktop::Zeroconf;
            item.favorite = false;
            remoteDesktops.append(item);
260 261
        }
    }
Tony Murray's avatar
Tony Murray committed
262
    reset();
263 264 265
}
#endif

266
#include "remotedesktopsmodel.moc"