remotedesktopsmodel.cpp 11.4 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
{
58
    return 6;  // same as count of RemoteDesktopsModel::DisplayItems enum
Tony Murray's avatar
Tony Murray committed
59
}
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
        switch (index.column()) {
        case RemoteDesktopsModel::Favorite:
            return item.favorite;
        case RemoteDesktopsModel::Title:
            return item.title;
        case RemoteDesktopsModel::LastConnected:
            return QVariant(item.lastConnected.dateTime());
111 112 113 114 115
        case RemoteDesktopsModel::VisitCount:
            return item.visits;
        case RemoteDesktopsModel::Created:
            if (item.created.isNull()) return QVariant();
            return KGlobal::locale()->formatDateTime(item.created.toLocalZone(), KLocale::FancyShortDate);
Tony Murray's avatar
Tony Murray committed
116 117 118 119 120 121 122 123 124 125 126 127 128 129
        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();
        }
130

Tony Murray's avatar
Tony Murray committed
131 132 133 134
    case Qt::CheckStateRole:
        if (index.column() == RemoteDesktopsModel::Favorite)
            return item.favorite ? Qt::Checked : Qt::Unchecked;
        return QVariant();
135

136
    case Qt::ToolTipRole:
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);
147 148 149 150 151 152 153
            }
            break; // else show default tooltip
        case RemoteDesktopsModel::Created:
            if (!item.created.isNull()) {
                return KGlobal::locale()->formatDateTime(item.created.toLocalZone(), KLocale::FancyLongDate);
            }
            break; // else show default tooltip
154
        default:
155
            break;
156
        }
157 158
        return item.url;  //use the url for the tooltip
        
159
    case 10001: //url for dockwidget
Tony Murray's avatar
Tony Murray committed
160
        return item.url;
161

162
    case 10002: //filter
Tony Murray's avatar
Tony Murray committed
163
        return item.url + item.title; // return both uservisible and data
164

165
    case 10003: //title for dockwidget
166 167
        return item.title;

168 169 170
    default:
        return QVariant();
    }
171 172 173
}

QVariant RemoteDesktopsModel::headerData(int section, Qt::Orientation orientation,
Tony Murray's avatar
Tony Murray committed
174
        int role) const
175
{
Tony Murray's avatar
Tony Murray committed
176 177 178 179 180
    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:
181
            return i18nc("Header of the connections list, title/url for remote connection", "Remote Desktop");
Tony Murray's avatar
Tony Murray committed
182
        case RemoteDesktopsModel::LastConnected:
183 184 185 186 187
            return i18nc("Header of the connections list, the last time this connection was initiated", "Last Connected");
        case RemoteDesktopsModel::VisitCount:
            return i18nc("Header of the connections list, the number of times this connection has been visited", "Visits");
        case RemoteDesktopsModel::Created:
            return i18nc("Header of the connections list, the time when this entry was created", "Created");
Tony Murray's avatar
Tony Murray committed
188
        case RemoteDesktopsModel::Source:
189
            return i18nc("Header of the connections list, where this entry comes from", "Source");
Tony Murray's avatar
Tony Murray committed
190 191
        }
    }
192 193 194
    return QVariant();
}

Tony Murray's avatar
Tony Murray committed
195 196
// does not trigger view update, you must do this by hand after using this function
void RemoteDesktopsModel::removeAllItemsFromSources(RemoteDesktop::Sources sources)
197
{
Tony Murray's avatar
Tony Murray committed
198 199 200 201 202 203 204
    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();
    }
205 206
}

Tony Murray's avatar
Tony Murray committed
207
void RemoteDesktopsModel::bookmarksChanged()
208
{
Tony Murray's avatar
Tony Murray committed
209 210 211 212
    kDebug(5010);
    removeAllItemsFromSources(RemoteDesktop::Bookmarks | RemoteDesktop::History);
    buildModelFromBookmarkGroup(m_manager->root());
    reset();
213 214
}

215
// Danger Will Roobinson, confusing code ahead!
Tony Murray's avatar
Tony Murray committed
216
void RemoteDesktopsModel::buildModelFromBookmarkGroup(const KBookmarkGroup &group)
217 218 219
{
    KBookmark bm = group.first();
    while (!bm.isNull()) {
Tony Murray's avatar
Tony Murray committed
220 221 222 223 224 225 226 227
        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();
228 229
            int index = remoteDesktops.indexOf(item); //search for this url to see if we need to update it
            bool newItem = index < 0; // do we need to create a new item?
Tony Murray's avatar
Tony Murray committed
230 231 232

            // 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") {
233 234 235 236 237
                // set source and favorite (will override later if needed)
                item.source = RemoteDesktop::History;
                item.favorite = false;

                // since we are in the history folder collect statitics and add them
Tony Murray's avatar
Tony Murray committed
238
                KDateTime connected = KDateTime();
239
                KDateTime created = KDateTime();
Tony Murray's avatar
Tony Murray committed
240
                bool ok = false;
241 242 243 244 245
                // first the created datetime
                created.setTime_t(bm.metaDataItem("time_added").toLongLong(&ok));
                if (ok) (newItem ? item : remoteDesktops[index]).created = created;
                // then the last visited datetime
                ok = false;
Tony Murray's avatar
Tony Murray committed
246
                connected.setTime_t(bm.metaDataItem("time_visited").toLongLong(&ok));
247 248 249 250 251
                if (ok) (newItem ? item : remoteDesktops[index]).lastConnected = connected;
                // finally the visited count
                ok = false;
                int visits = bm.metaDataItem("visit_count").toInt(&ok);
                if (ok) (newItem ? item : remoteDesktops[index]).visits = visits;
Tony Murray's avatar
Tony Murray committed
252 253
            } else {
                if (newItem) {
254
                    // if this is a new item, just add the rest of the required data
Tony Murray's avatar
Tony Murray committed
255
                    item.lastConnected = KDateTime();
256 257
                    item.created = KDateTime();
                    item.visits = 0;
Tony Murray's avatar
Tony Murray committed
258 259 260
                    item.favorite = true;
                    item.source = RemoteDesktop::Bookmarks;
                } else {
261
                    // otherwise override these fields with the info from the bookmark
Tony Murray's avatar
Tony Murray committed
262 263
                    remoteDesktops[index].title = bm.text();
                    remoteDesktops[index].favorite = true;
264
                    remoteDesktops[index].source = RemoteDesktop::Bookmarks;
Tony Murray's avatar
Tony Murray committed
265 266
                }
            }
267
            // if we have a new item, add it
Tony Murray's avatar
Tony Murray committed
268 269 270 271
            if (newItem)
                remoteDesktops.append(item);
        }
        bm = group.next(bm); // next item in the group
272 273 274
    }
}

275
#ifdef BUILD_ZEROCONF
Tony Murray's avatar
Tony Murray committed
276 277 278
void RemoteDesktopsModel::servicesChanged()
{
    //redo list because it is easier than finding and removing one that disappeared
279 280
    QList<DNSSD::RemoteService::Ptr> services = zeroconfBrowser->services();
    KUrl url;
Tony Murray's avatar
Tony Murray committed
281
    removeAllItemsFromSources(RemoteDesktop::Zeroconf);
282 283 284 285
    foreach(DNSSD::RemoteService::Ptr service, services) {
        url.setProtocol(m_protocols[service->type()].toLower());
        url.setHost(service->hostName());
        url.setPort(service->port());
286

Tony Murray's avatar
Tony Murray committed
287 288
        RemoteDesktop item;
        item.url = url.url();
289

Tony Murray's avatar
Tony Murray committed
290 291 292 293 294
        if (!remoteDesktops.contains(item)) {
            item.title = service->serviceName();
            item.source = RemoteDesktop::Zeroconf;
            item.favorite = false;
            remoteDesktops.append(item);
295 296
        }
    }
Tony Murray's avatar
Tony Murray committed
297
    reset();
298 299 300
}
#endif

301
#include "remotedesktopsmodel.moc"