From f31405743e2cdd1fe1754f7157ea48b048daa1fc Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Thu, 19 Nov 2009 17:12:44 +0100 Subject: [PATCH] initial commit for deck repository tab --- cockatrice/cockatrice.pro | 2 + cockatrice/cockatrice.qrc | 3 +- cockatrice/resources/arrow_left_green.svg | 792 ++++++++++++++++++ ...{add_to_deck.svg => arrow_right_green.svg} | 0 cockatrice/src/tab_deck_storage.cpp | 179 ++++ cockatrice/src/tab_deck_storage.h | 44 + cockatrice/src/tab_supervisor.cpp | 12 +- cockatrice/src/tab_supervisor.h | 2 + cockatrice/src/window_deckeditor.cpp | 2 +- common/protocol.cpp | 3 +- common/protocol.h | 6 +- servatrice/src/serversocketinterface.cpp | 12 +- 12 files changed, 1047 insertions(+), 10 deletions(-) create mode 100644 cockatrice/resources/arrow_left_green.svg rename cockatrice/resources/{add_to_deck.svg => arrow_right_green.svg} (100%) create mode 100644 cockatrice/src/tab_deck_storage.cpp create mode 100644 cockatrice/src/tab_deck_storage.h diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index c2533b8e..96694aec 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -43,6 +43,7 @@ HEADERS += src/counter.h \ src/tab_server.h \ src/tab_chatchannel.h \ src/tab_game.h \ + src/tab_deck_storage.h \ src/tab_supervisor.h \ ../common/decklist.h \ ../common/protocol.h \ @@ -86,6 +87,7 @@ SOURCES += src/counter.cpp \ src/tab_server.cpp \ src/tab_chatchannel.cpp \ src/tab_game.cpp \ + src/tab_deck_storage.cpp \ src/tab_supervisor.cpp \ ../common/decklist.cpp \ ../common/protocol.cpp \ diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index bd74e5c2..8d3ef904 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -20,10 +20,11 @@ translations/cockatrice_de.qm translations/cockatrice_en.qm resources/icon.svg - resources/add_to_deck.svg resources/add_to_sideboard.svg resources/decrement.svg resources/increment.svg resources/remove_row.svg + resources/arrow_left_green.svg + resources/arrow_right_green.svg diff --git a/cockatrice/resources/arrow_left_green.svg b/cockatrice/resources/arrow_left_green.svg new file mode 100644 index 00000000..f01f4b4f --- /dev/null +++ b/cockatrice/resources/arrow_left_green.svg @@ -0,0 +1,792 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/cockatrice/resources/add_to_deck.svg b/cockatrice/resources/arrow_right_green.svg similarity index 100% rename from cockatrice/resources/add_to_deck.svg rename to cockatrice/resources/arrow_right_green.svg diff --git a/cockatrice/src/tab_deck_storage.cpp b/cockatrice/src/tab_deck_storage.cpp new file mode 100644 index 00000000..c9c49664 --- /dev/null +++ b/cockatrice/src/tab_deck_storage.cpp @@ -0,0 +1,179 @@ +#include +#include +#include "tab_deck_storage.h" +#include "client.h" +#include "decklist.h" +#include "protocol_items.h" + +enum { TWIFolderType = QTreeWidgetItem::UserType + 1, TWIDeckType = QTreeWidgetItem::UserType + 2 }; + +TabDeckStorage::TabDeckStorage(Client *_client) + : QWidget(), client(_client) +{ + localDirModel = new QFileSystemModel(this); + QSettings settings; + localDirModel->setRootPath(settings.value("paths/decks").toString()); + + sortFilter = new QSortFilterProxyModel(this); + sortFilter->setSourceModel(localDirModel); + sortFilter->setDynamicSortFilter(true); + + localDirView = new QTreeView; + localDirView->setModel(sortFilter); + localDirView->setColumnHidden(1, true); + localDirView->setRootIndex(sortFilter->mapFromSource(localDirModel->index(localDirModel->rootPath(), 0))); + localDirView->setSortingEnabled(true); + localDirView->header()->setResizeMode(QHeaderView::ResizeToContents); + + QVBoxLayout *leftVbox = new QVBoxLayout; + leftVbox->addWidget(localDirView); + leftGroupBox = new QGroupBox; + leftGroupBox->setLayout(leftVbox); + + toolBar = new QToolBar; + toolBar->setOrientation(Qt::Vertical); + toolBar->setIconSize(QSize(24, 24)); + + serverDirView = new QTreeWidget; + serverDirView->header()->setResizeMode(QHeaderView::ResizeToContents); + serverDirView->setColumnCount(3); + + QVBoxLayout *rightVbox = new QVBoxLayout; + rightVbox->addWidget(serverDirView); + rightGroupBox = new QGroupBox; + rightGroupBox->setLayout(rightVbox); + + QHBoxLayout *hbox = new QHBoxLayout; + hbox->addWidget(leftGroupBox); + hbox->addWidget(toolBar); + hbox->addWidget(rightGroupBox); + + aUpload = new QAction(this); + aUpload->setIcon(QIcon(":/resources/arrow_right_green.svg")); + connect(aUpload, SIGNAL(triggered()), this, SLOT(actUpload())); + aDownload = new QAction(this); + aDownload->setIcon(QIcon(":/resources/arrow_left_green.svg")); + connect(aDownload, SIGNAL(triggered()), this, SLOT(actDownload())); + aNewFolder = new QAction(this); + connect(aNewFolder, SIGNAL(triggered()), this, SLOT(actNewFolder())); + aDelete = new QAction(this); + aDelete->setIcon(QIcon(":/resources/remove_row.svg")); + connect(aDelete, SIGNAL(triggered()), this, SLOT(actDelete())); + + toolBar->addAction(aUpload); + toolBar->addAction(aDownload); + toolBar->addAction(aNewFolder); + toolBar->addAction(aDelete); + + retranslateUi(); + setLayout(hbox); + + refreshServerList(); +} + +void TabDeckStorage::retranslateUi() +{ + leftGroupBox->setTitle(tr("Local file system")); + rightGroupBox->setTitle(tr("Server deck storage")); + + aUpload->setText(tr("Upload deck")); + aDownload->setText(tr("Download deck")); + aNewFolder->setText(tr("New folder")); + aDelete->setText(tr("Delete")); + + QTreeWidgetItem *header = serverDirView->headerItem(); + header->setText(0, tr("Name")); + header->setText(1, tr("ID")); + header->setText(2, tr("Upload time")); + header->setTextAlignment(1, Qt::AlignRight); +} + +void TabDeckStorage::refreshServerList() +{ + Command_DeckList *command = new Command_DeckList; + connect(command, SIGNAL(finished(ProtocolResponse *)), this, SLOT(deckListFinished(ProtocolResponse *))); + client->sendCommand(command); +} + +void TabDeckStorage::populateDeckList(Response_DeckList::Directory *folder, QTreeWidgetItem *parent) +{ + QFileIconProvider fip; + QTreeWidgetItem *newItem = new QTreeWidgetItem(TWIFolderType); + newItem->setIcon(0, fip.icon(QFileIconProvider::Folder)); + newItem->setText(0, parent ? folder->getName() : "/"); + QString parentPath; + if (parent) { + parent->addChild(newItem); + parentPath = parent->data(0, Qt::UserRole).toString(); + } else + serverDirView->addTopLevelItem(newItem); + newItem->setData(0, Qt::UserRole, parentPath + "/" + folder->getName()); + + for (int i = 0; i < folder->size(); ++i) { + Response_DeckList::Directory *subFolder = dynamic_cast(folder->at(i)); + if (subFolder) + populateDeckList(subFolder, newItem); + else { + Response_DeckList::File *file = dynamic_cast(folder->at(i)); + QTreeWidgetItem *newDeck = new QTreeWidgetItem(TWIDeckType); + newDeck->setIcon(0, fip.icon(QFileIconProvider::File)); + newDeck->setData(0, Qt::DisplayRole, file->getName()); + newDeck->setData(1, Qt::DisplayRole, file->getId()); + newDeck->setTextAlignment(1, Qt::AlignRight); + newDeck->setData(2, Qt::DisplayRole, file->getUploadTime()); + + newItem->addChild(newDeck); + } + } +} + +void TabDeckStorage::deckListFinished(ProtocolResponse *r) +{ + Response_DeckList *resp = qobject_cast(r); + if (!resp) + return; + + serverDirView->clear(); + populateDeckList(resp->getRoot(), 0); +} + +void TabDeckStorage::actUpload() +{ + QModelIndex cur = sortFilter->mapToSource(localDirView->selectionModel()->currentIndex()); + if (localDirModel->isDir(cur)) + return; + QString filePath = localDirModel->filePath(cur); + DeckList *deck = new DeckList; + if (!deck->loadFromFile(filePath, DeckList::CockatriceFormat)) + return; + + QString targetPath; + QTreeWidgetItem *curRight = serverDirView->currentItem(); + while ((curRight != 0) && (curRight->type() != TWIFolderType)) + curRight = curRight->parent(); + if (curRight) + targetPath = curRight->data(0, Qt::UserRole).toString(); + qDebug() << "targetPath:" << targetPath; + + Command_DeckUpload *command = new Command_DeckUpload(-1, deck, targetPath); + connect(command, SIGNAL(finished(ProtocolResponse *)), this, SLOT(uploadFinished(ProtocolResponse *))); + client->sendCommand(command); +} + +void TabDeckStorage::uploadFinished(ProtocolResponse *r) +{ + qDebug() << "buh"; +} + +void TabDeckStorage::actDownload() +{ +} + +void TabDeckStorage::actNewFolder() +{ +} + +void TabDeckStorage::actDelete() +{ +} + diff --git a/cockatrice/src/tab_deck_storage.h b/cockatrice/src/tab_deck_storage.h new file mode 100644 index 00000000..52cc3c79 --- /dev/null +++ b/cockatrice/src/tab_deck_storage.h @@ -0,0 +1,44 @@ +#ifndef TAB_DECK_STORAGE_H +#define TAB_DECK_STORAGE_H + +#include +#include "protocol.h" + +class Client; +class QTreeView; +class QFileSystemModel; +class QSortFilterProxyModel; +class QToolBar; +class QTreeWidget; +class QTreeWidgetItem; +class QGroupBox; + +class TabDeckStorage : public QWidget { + Q_OBJECT +private: + Client *client; + QTreeView *localDirView; + QFileSystemModel *localDirModel; + QSortFilterProxyModel *sortFilter; + QToolBar *toolBar; + QTreeWidget *serverDirView; + QGroupBox *leftGroupBox, *rightGroupBox; + + QAction *aUpload, *aDownload, *aNewFolder, *aDelete; + void populateDeckList(Response_DeckList::Directory *folder, QTreeWidgetItem *parent); + void refreshServerList(); +private slots: + void deckListFinished(ProtocolResponse *r); + + void actUpload(); + void uploadFinished(ProtocolResponse *r); + + void actDownload(); + void actNewFolder(); + void actDelete(); +public: + TabDeckStorage(Client *_client); + void retranslateUi(); +}; + +#endif diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index b3a2fbb7..94985898 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -3,10 +3,11 @@ #include "tab_server.h" #include "tab_chatchannel.h" #include "tab_game.h" +#include "tab_deck_storage.h" #include "protocol_items.h" TabSupervisor:: TabSupervisor(QWidget *parent) - : QTabWidget(parent), client(0), tabServer(0) + : QTabWidget(parent), client(0), tabServer(0), tabDeckStorage(0) { } @@ -15,6 +16,8 @@ void TabSupervisor::retranslateUi() { if (tabServer) setTabText(0, tr("Server")); + if (tabDeckStorage) + setTabText(1, tr("Deck storage")); } void TabSupervisor::start(Client *_client) @@ -27,8 +30,10 @@ void TabSupervisor::start(Client *_client) tabServer = new TabServer(client); connect(tabServer, SIGNAL(gameJoined(int)), this, SLOT(addGameTab(int))); connect(tabServer, SIGNAL(chatChannelJoined(const QString &)), this, SLOT(addChatChannelTab(const QString &))); - addTab(tabServer, QString()); + + tabDeckStorage = new TabDeckStorage(client); + addTab(tabDeckStorage, QString()); retranslateUi(); } @@ -45,6 +50,9 @@ void TabSupervisor::stop() delete tabServer; tabServer = 0; + delete tabDeckStorage; + tabDeckStorage = 0; + QMapIterator chatChannelIterator(chatChannelTabs); while (chatChannelIterator.hasNext()) delete chatChannelIterator.next().value(); diff --git a/cockatrice/src/tab_supervisor.h b/cockatrice/src/tab_supervisor.h index b8f2e803..2724f108 100644 --- a/cockatrice/src/tab_supervisor.h +++ b/cockatrice/src/tab_supervisor.h @@ -8,6 +8,7 @@ class Client; class TabServer; class TabChatChannel; class TabGame; +class TabDeckStorage; class ChatEvent; class GameEvent; class Event_GameJoined; @@ -17,6 +18,7 @@ class TabSupervisor : public QTabWidget { private: Client *client; TabServer *tabServer; + TabDeckStorage *tabDeckStorage; QMap chatChannelTabs; QMap gameTabs; public: diff --git a/cockatrice/src/window_deckeditor.cpp b/cockatrice/src/window_deckeditor.cpp index 1a3ebd56..cac83eb5 100644 --- a/cockatrice/src/window_deckeditor.cpp +++ b/cockatrice/src/window_deckeditor.cpp @@ -141,7 +141,7 @@ WndDeckEditor::WndDeckEditor(QWidget *parent) aAddCard = new QAction(tr("Add card to &maindeck"), this); aAddCard->setShortcuts(QList() << QKeySequence(tr("Return")) << QKeySequence(tr("Enter"))); - aAddCard->setIcon(QIcon(":/resources/add_to_deck.svg")); + aAddCard->setIcon(QIcon(":/resources/arrow_right_green.svg")); connect(aAddCard, SIGNAL(triggered()), this, SLOT(actAddCard())); aAddCardToSideboard = new QAction(tr("Add card to &sideboard"), this); aAddCardToSideboard->setIcon(QIcon(":/resources/add_to_sideboard.svg")); diff --git a/common/protocol.cpp b/common/protocol.cpp index 70b81cb2..932eac17 100644 --- a/common/protocol.cpp +++ b/common/protocol.cpp @@ -187,6 +187,7 @@ void Response_DeckList::File::writeElement(QXmlStreamWriter *xml) xml->writeStartElement("file"); xml->writeAttribute("name", name); xml->writeAttribute("id", QString::number(id)); + xml->writeAttribute("upload_time", QString::number(uploadTime.toTime_t())); xml->writeEndElement(); } @@ -207,7 +208,7 @@ bool Response_DeckList::Directory::readElement(QXmlStreamReader *xml) currentItem = new Directory(xml->attributes().value("name").toString()); append(currentItem); } else if (xml->isStartElement() && (xml->name() == "file")) { - currentItem = new File(xml->attributes().value("name").toString(), xml->attributes().value("id").toString().toInt()); + currentItem = new File(xml->attributes().value("name").toString(), xml->attributes().value("id").toString().toInt(), QDateTime::fromTime_t(xml->attributes().value("upload_time").toString().toUInt())); append(currentItem); } else if (xml->isEndElement() && (xml->name() == "directory")) return true; diff --git a/common/protocol.h b/common/protocol.h index 238d4ba9..d940065e 100644 --- a/common/protocol.h +++ b/common/protocol.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "protocol_item_ids.h" #include "protocol_datastructures.h" @@ -180,10 +181,13 @@ public: virtual void writeElement(QXmlStreamWriter *xml) = 0; }; class File : public TreeItem { + private: + QDateTime uploadTime; public: - File(const QString &_name, int _id) : TreeItem(_name, _id) { } + File(const QString &_name, int _id, QDateTime _uploadTime) : TreeItem(_name, _id), uploadTime(_uploadTime) { } bool readElement(QXmlStreamReader *xml); void writeElement(QXmlStreamWriter *xml); + QDateTime getUploadTime() const { return uploadTime; } }; class Directory : public TreeItem, public QList { private: diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 676956a2..db7e946c 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -151,13 +151,13 @@ bool ServerSocketInterface::deckListHelper(Response_DeckList::Directory *folder) return false; } - query.prepare("select id, name from decklist_files where id_folder = :id_folder"); + query.prepare("select id, name, upload_time from decklist_files where id_folder = :id_folder"); query.bindValue(":id_folder", folder->getId()); if (!servatrice->execSqlQuery(query)) return false; while (query.next()) { - Response_DeckList::File *newFile = new Response_DeckList::File(query.value(1).toString(), query.value(0).toInt()); + Response_DeckList::File *newFile = new Response_DeckList::File(query.value(1).toString(), query.value(0).toInt(), query.value(2).toDateTime()); folder->append(newFile); } @@ -267,11 +267,15 @@ ResponseCode ServerSocketInterface::cmdDeckUpload(Command_DeckUpload *cmd) cmd->getDeck()->writeElement(&deckWriter); deckWriter.writeEndDocument(); + QString deckName = cmd->getDeck()->getName(); + if (deckName.isEmpty()) + deckName = "Unnamed deck"; + QSqlQuery query; - query.prepare("insert into decklist_files (id_folder, user, name, content) value(:id_folder, :user, :name, :content)"); + query.prepare("insert into decklist_files (id_folder, user, name, upload_time, content) values(:id_folder, :user, :name, NOW(), :content)"); query.bindValue(":id_folder", folderId); query.bindValue(":user", playerName); - query.bindValue(":name", cmd->getDeck()->getName()); + query.bindValue(":name", deckName); query.bindValue(":content", deckContents); servatrice->execSqlQuery(query);