From f7252fd69353ef3cb9e3b3512b4507c03a829c37 Mon Sep 17 00:00:00 2001 From: thunder2 Date: Fri, 3 Dec 2010 00:54:40 +0000 Subject: [PATCH] Added three new methods on misc: getOpenFileName, getOpenFileNames and getSaveFileName. Please use this rather than QFileDialog. Added save and restore of the last used directories for the following types - Extra files - Certificates - History - Images - Messages - Blogs (not tested) It is easy to change. Added attach of multiple files at once in CreateForumMsg. The RetroShare links of the added files in CreateForumMsg are added with new style and as anchor with size information. Added translation to some file dialogs. Removed (commented out) not needed methods in NetworkDialog. Fixed handling of filenames with umlauts when adding extra files. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@3894 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- retroshare-gui/src/RetroShare.pro | 1 + retroshare-gui/src/gui/MessengerWindow.cpp | 1 - retroshare-gui/src/gui/NetworkDialog.cpp | 313 +++++++++--------- retroshare-gui/src/gui/NetworkDialog.h | 8 +- retroshare-gui/src/gui/PeersDialog.cpp | 38 +-- .../src/gui/PluginManagerWidget.cpp | 1 - .../src/gui/RSHumanReadableDelegate.h | 1 + retroshare-gui/src/gui/SearchDialog.cpp | 1 + .../src/gui/channels/CreateChannel.cpp | 5 +- .../src/gui/channels/CreateChannelMsg.cpp | 20 +- .../src/gui/chat/PopupChatDialog.cpp | 40 +-- .../src/gui/chat/PopupChatWindow.cpp | 8 +- .../src/gui/forums/CreateForumMsg.cpp | 32 +- .../src/gui/msgs/MessageComposer.cpp | 52 ++- .../src/gui/settings/CryptoPage.cpp | 15 +- .../src/gui/settings/rsharesettings.cpp | 39 +++ .../src/gui/settings/rsharesettings.h | 15 +- .../src/gui/unfinished/blogs/CreateBlog.cpp | 6 +- .../gui/unfinished/blogs/CreateBlogMsg.cpp | 48 ++- retroshare-gui/src/lang/retroshare_de.qm | Bin 276563 -> 275486 bytes retroshare-gui/src/lang/retroshare_de.ts | 223 +++++++------ retroshare-gui/src/util/misc.cpp | 286 ++++++++++++++++ retroshare-gui/src/util/misc.h | 309 +++-------------- 23 files changed, 786 insertions(+), 676 deletions(-) create mode 100644 retroshare-gui/src/util/misc.cpp diff --git a/retroshare-gui/src/RetroShare.pro b/retroshare-gui/src/RetroShare.pro index 1a6f5acaa..56b3cf2c6 100644 --- a/retroshare-gui/src/RetroShare.pro +++ b/retroshare-gui/src/RetroShare.pro @@ -463,6 +463,7 @@ SOURCES += main.cpp \ util/rsversion.cpp \ util/printpreview.cpp \ util/log.cpp \ + util/misc.cpp \ gui/bwgraph/bwgraph.cpp \ gui/profile/ProfileView.cpp \ gui/profile/ProfileEdit.cpp \ diff --git a/retroshare-gui/src/gui/MessengerWindow.cpp b/retroshare-gui/src/gui/MessengerWindow.cpp index cf1d552f0..a89189fc4 100644 --- a/retroshare-gui/src/gui/MessengerWindow.cpp +++ b/retroshare-gui/src/gui/MessengerWindow.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include "common/vmessagebox.h" #include "common/StatusDefs.h" diff --git a/retroshare-gui/src/gui/NetworkDialog.cpp b/retroshare-gui/src/gui/NetworkDialog.cpp index 535bcb66b..058dfb1c7 100644 --- a/retroshare-gui/src/gui/NetworkDialog.cpp +++ b/retroshare-gui/src/gui/NetworkDialog.cpp @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -294,51 +293,48 @@ void NetworkDialog::peerdetails() } /** Open a QFileDialog to browse for a pem/pqi file. */ -void NetworkDialog::loadcert() -{ - /* Create a new input dialog, which allows users to create files, too */ - QFileDialog dialog (this, tr("Select a pem/pqi File")); - //dialog.setDirectory(QFileInfo(ui.lineTorConfig->text()).absoluteDir()); - //dialog.selectFile(QFileInfo(ui.lineTorConfig->text()).fileName()); - dialog.setFileMode(QFileDialog::AnyFile); - dialog.setReadOnly(false); - - /* Prompt the user to select a file or create a new one */ - if (!dialog.exec() || dialog.selectedFiles().isEmpty()) { - return; - } - QString filename = QDir::convertSeparators(dialog.selectedFiles().at(0)); - - /* Check if the file exists */ - QFile torrcFile(filename); - if (!QFileInfo(filename).exists()) { - /* The given file does not exist. Should we create it? */ - int response = VMessageBox::question(this, - tr("File Not Found"), - tr("%1 does not exist. Would you like to create it?") - .arg(filename), - VMessageBox::Yes, VMessageBox::No); - - if (response == VMessageBox::No) { - /* Don't create it. Just bail. */ - return; - } - /* Attempt to create the specified file */ - if (!torrcFile.open(QIODevice::WriteOnly)) { - VMessageBox::warning(this, - tr("Failed to Create File"), - tr("Unable to create %1 [%2]").arg(filename) - .arg(torrcFile.errorString()), - VMessageBox::Ok); - return; - } - } - //ui.lineTorConfig->setText(filename); -} - - - -#include +//void NetworkDialog::loadcert() +//{ +// use misc::getOpenFileName +// /* Create a new input dialog, which allows users to create files, too */ +// QFileDialog dialog (this, tr("Select a pem/pqi File")); +// //dialog.setDirectory(QFileInfo(ui.lineTorConfig->text()).absoluteDir()); +// //dialog.selectFile(QFileInfo(ui.lineTorConfig->text()).fileName()); +// dialog.setFileMode(QFileDialog::AnyFile); +// dialog.setReadOnly(false); +// +// /* Prompt the user to select a file or create a new one */ +// if (!dialog.exec() || dialog.selectedFiles().isEmpty()) { +// return; +// } +// QString filename = QDir::convertSeparators(dialog.selectedFiles().at(0)); +// +// /* Check if the file exists */ +// QFile torrcFile(filename); +// if (!QFileInfo(filename).exists()) { +// /* The given file does not exist. Should we create it? */ +// int response = VMessageBox::question(this, +// tr("File Not Found"), +// tr("%1 does not exist. Would you like to create it?") +// .arg(filename), +// VMessageBox::Yes, VMessageBox::No); +// +// if (response == VMessageBox::No) { +// /* Don't create it. Just bail. */ +// return; +// } +// /* Attempt to create the specified file */ +// if (!torrcFile.open(QIODevice::WriteOnly)) { +// VMessageBox::warning(this, +// tr("Failed to Create File"), +// tr("Unable to create %1 [%2]").arg(filename) +// .arg(torrcFile.errorString()), +// VMessageBox::Ok); +// return; +// } +// } +// //ui.lineTorConfig->setText(filename); +//} void NetworkDialog::updateDisplay() { @@ -580,128 +576,131 @@ RsCertId getNeighRsCertId(QTreeWidgetItem *i) * All of these rely on the finding of the current Id. */ -std::string NetworkDialog::loadneighbour() -{ -#ifdef NET_DEBUG - std::cerr << "NetworkDialog::loadneighbour()" << std::endl; -#endif - QString fileName = QFileDialog::getOpenFileName(this, tr("Select Certificate"), "", - tr("Certificates (*.pqi *.pem)")); +//std::string NetworkDialog::loadneighbour() +//{ +//#ifdef NET_DEBUG +// std::cerr << "NetworkDialog::loadneighbour()" << std::endl; +//#endif +// use misc::getOpenFileName +// QString fileName = QFileDialog::getOpenFileName(this, tr("Select Certificate"), "", +// tr("Certificates (*.pqi *.pem)")); +// +// std::string file = fileName.toStdString(); +// std::string id; +// std::string gpg_id; +// if (file != "") +// { +// rsPeers->loadCertificateFromFile(file, id, gpg_id); +// } +// return id; +//} - std::string file = fileName.toStdString(); - std::string id; - std::string gpg_id; - if (file != "") - { - rsPeers->loadCertificateFromFile(file, id, gpg_id); - } - return id; -} +//void NetworkDialog::addneighbour() +//{ +//// QTreeWidgetItem *c = getCurrentNeighbour(); +//#ifdef NET_DEBUG +// std::cerr << "NetworkDialog::addneighbour()" << std::endl; +//#endif +// /* +// rsServer->NeighAddFriend(getNeighRsCertId(c)); +// */ +//} -void NetworkDialog::addneighbour() -{ -// QTreeWidgetItem *c = getCurrentNeighbour(); -#ifdef NET_DEBUG - std::cerr << "NetworkDialog::addneighbour()" << std::endl; -#endif - /* - rsServer->NeighAddFriend(getNeighRsCertId(c)); - */ -} - -void NetworkDialog::authneighbour() -{ -// QTreeWidgetItem *c = getCurrentNeighbour(); -#ifdef NET_DEBUG - std::cerr << "NetworkDialog::authneighbour()" << std::endl; -#endif - /* - RsAuthId code; - rsServer->NeighAuthFriend(getNeighRsCertId(c), code); - */ -} +//void NetworkDialog::authneighbour() +//{ +//// QTreeWidgetItem *c = getCurrentNeighbour(); +//#ifdef NET_DEBUG +// std::cerr << "NetworkDialog::authneighbour()" << std::endl; +//#endif +// /* +// RsAuthId code; +// rsServer->NeighAuthFriend(getNeighRsCertId(c), code); +// */ +//} /** Open a QFileDialog to browse for a pem/pqi file. */ void NetworkDialog::on_actionAddFriend_activated() { - /* Create a new input dialog, which allows users to create files, too */ - QFileDialog dialog (this, tr("Select a pem/pqi File")); - //dialog.setDirectory(QFileInfo(ui.lineTorConfig->text()).absoluteDir()); - //dialog.selectFile(QFileInfo(ui.lineTorConfig->text()).fileName()); - dialog.setFileMode(QFileDialog::AnyFile); - dialog.setReadOnly(false); - - /* Prompt the user to select a file or create a new one */ - if (!dialog.exec() || dialog.selectedFiles().isEmpty()) { - return; - } - QString filename = QDir::convertSeparators(dialog.selectedFiles().at(0)); - - /* Check if the file exists */ - QFile torrcFile(filename); - if (!QFileInfo(filename).exists()) { - /* The given file does not exist. Should we create it? */ - int response = VMessageBox::question(this, - tr("File Not Found"), - tr("%1 does not exist. Would you like to create it?") - .arg(filename), - VMessageBox::Yes, VMessageBox::No); - - if (response == VMessageBox::No) { - /* Don't create it. Just bail. */ - return; - } - /* Attempt to create the specified file */ - if (!torrcFile.open(QIODevice::WriteOnly)) { - VMessageBox::warning(this, - tr("Failed to Create File"), - tr("Unable to create %1 [%2]").arg(filename) - .arg(torrcFile.errorString()), - VMessageBox::Ok); - return; - } - } - //ui.lineTorConfig->setText(filename); +// /* Create a new input dialog, which allows users to create files, too */ +// use misc::getOpenFileName +// QFileDialog dialog (this, tr("Select a pem/pqi File")); +// //dialog.setDirectory(QFileInfo(ui.lineTorConfig->text()).absoluteDir()); +// //dialog.selectFile(QFileInfo(ui.lineTorConfig->text()).fileName()); +// dialog.setFileMode(QFileDialog::AnyFile); +// dialog.setReadOnly(false); +// +// /* Prompt the user to select a file or create a new one */ +// if (!dialog.exec() || dialog.selectedFiles().isEmpty()) { +// return; +// } +// QString filename = QDir::convertSeparators(dialog.selectedFiles().at(0)); +// +// /* Check if the file exists */ +// QFile torrcFile(filename); +// if (!QFileInfo(filename).exists()) { +// /* The given file does not exist. Should we create it? */ +// int response = VMessageBox::question(this, +// tr("File Not Found"), +// tr("%1 does not exist. Would you like to create it?") +// .arg(filename), +// VMessageBox::Yes, VMessageBox::No); +// +// if (response == VMessageBox::No) { +// /* Don't create it. Just bail. */ +// return; +// } +// /* Attempt to create the specified file */ +// if (!torrcFile.open(QIODevice::WriteOnly)) { +// VMessageBox::warning(this, +// tr("Failed to Create File"), +// tr("Unable to create %1 [%2]").arg(filename) +// .arg(torrcFile.errorString()), +// VMessageBox::Ok); +// return; +// } +// } +// //ui.lineTorConfig->setText(filename); } void NetworkDialog::on_actionExportKey_activated() { - qDebug() << " exportcert"; - - std::string cert = rsPeers->GetRetroshareInvite(); - if (cert.empty()) { - QMessageBox::information(this, tr("RetroShare"), - tr("Sorry, create certificate failed"), - QMessageBox::Ok, QMessageBox::Ok); - return; - } - - QString qdir = QFileDialog::getSaveFileName(this, - tr("Please choose a filename"), - QDir::homePath(), - tr("RetroShare Certificate (*.rsc );;All Files (*)")); - //Todo: move save to file to p3Peers::SaveCertificateToFile - - if (qdir.isEmpty() == false) { - QFile CertFile (qdir); - if (CertFile.open(QIODevice::WriteOnly/* | QIODevice::Text*/)) { - if (CertFile.write(QByteArray(cert.c_str())) > 0) { - QMessageBox::information(this, tr("RetroShare"), - tr("Certificate file successfully created"), - QMessageBox::Ok, QMessageBox::Ok); - } else { - QMessageBox::information(this, tr("RetroShare"), - tr("Sorry, certificate file creation failed"), - QMessageBox::Ok, QMessageBox::Ok); - } - CertFile.close(); - } else { - QMessageBox::information(this, tr("RetroShare"), - tr("Sorry, certificate file creation failed"), - QMessageBox::Ok, QMessageBox::Ok); - } - } +// qDebug() << " exportcert"; +// +// std::string cert = rsPeers->GetRetroshareInvite(); +// if (cert.empty()) { +// QMessageBox::information(this, tr("RetroShare"), +// tr("Sorry, create certificate failed"), +// QMessageBox::Ok, QMessageBox::Ok); +// return; +// } +// +// use misc::getSaveFileName +// QString qdir = QFileDialog::getSaveFileName(this, +// tr("Please choose a filename"), +// QDir::homePath(), +// tr("RetroShare Certificate (*.rsc );;All Files (*)")); +// //Todo: move save to file to p3Peers::SaveCertificateToFile +// +// if (qdir.isEmpty() == false) { +// QFile CertFile (qdir); +// if (CertFile.open(QIODevice::WriteOnly/* | QIODevice::Text*/)) { +// if (CertFile.write(QByteArray(cert.c_str())) > 0) { +// QMessageBox::information(this, tr("RetroShare"), +// tr("Certificate file successfully created"), +// QMessageBox::Ok, QMessageBox::Ok); +// } else { +// QMessageBox::information(this, tr("RetroShare"), +// tr("Sorry, certificate file creation failed"), +// QMessageBox::Ok, QMessageBox::Ok); +// } +// CertFile.close(); +// } else { +// QMessageBox::information(this, tr("RetroShare"), +// tr("Sorry, certificate file creation failed"), +// QMessageBox::Ok, QMessageBox::Ok); +// } +// } } void NetworkDialog::on_actionCreate_New_Profile_activated() diff --git a/retroshare-gui/src/gui/NetworkDialog.h b/retroshare-gui/src/gui/NetworkDialog.h index ed88c7343..91fb0611a 100644 --- a/retroshare-gui/src/gui/NetworkDialog.h +++ b/retroshare-gui/src/gui/NetworkDialog.h @@ -39,7 +39,7 @@ public: public slots: void insertConnect(); - std::string loadneighbour(); +// std::string loadneighbour(); /* void loadneighbour(); */ void updateNewDiscoveryInfo() ; @@ -55,10 +55,10 @@ private slots: //void unvalidGPGkeyWidgetCostumPopupMenu( QPoint point ); /** Called when user clicks "Load Cert" to choose location of a Cert file */ - void loadcert(); +// void loadcert(); - void authneighbour(); - void addneighbour(); +// void authneighbour(); +// void addneighbour(); void on_actionAddFriend_activated(); //void on_actionCopyKey_activated(); diff --git a/retroshare-gui/src/gui/PeersDialog.cpp b/retroshare-gui/src/gui/PeersDialog.cpp index aab93bfa0..2615e246c 100644 --- a/retroshare-gui/src/gui/PeersDialog.cpp +++ b/retroshare-gui/src/gui/PeersDialog.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include "common/vmessagebox.h" #include "common/StatusDefs.h" #include "common/GroupDefs.h" @@ -64,6 +63,7 @@ #include "MainWindow.h" #include "NewsFeed.h" +#include "util/misc.h" #include #include @@ -1103,18 +1103,15 @@ void PeersDialog::exportfriend() } std::string id = getPeerRsCertId(c); - QString fileName = QFileDialog::getSaveFileName(this, tr("Save Certificate"), "", - tr("Certificates (*.pqi)")); - std::string file = fileName.toStdString(); - if (file != "") + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_CERT, tr("Save Certificate"), tr("Certificates (*.pqi)"), fileName)) { #ifdef PEERS_DEBUG std::cerr << "PeersDialog::exportfriend() Saving to: " << file << std::endl; #endif if (rsPeers) { - rsPeers->saveCertificateToFile(id, file); + rsPeers->saveCertificateToFile(id, fileName.toUtf8().constData()); } } @@ -1727,8 +1724,8 @@ void PeersDialog::updateAvatar() void PeersDialog::getAvatar() { - QString fileName = QFileDialog::getOpenFileName(this, "Load File", QDir::homePath(), "Pictures (*.png *.xpm *.jpg *.tiff *.gif)"); - if(!fileName.isEmpty()) + QString fileName; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Load File"), tr("Pictures (*.png *.xpm *.jpg *.tiff *.gif)"), fileName)) { QPixmap picture; picture = QPixmap(fileName).scaled(96,96, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); @@ -1794,14 +1791,10 @@ void PeersDialog::statusmessage() void PeersDialog::addExtraFile() { - // select a file - QString qfile = QFileDialog::getOpenFileName(this, tr("Add Extra File"), "", "", 0, - QFileDialog::DontResolveSymlinks); - std::string filePath = qfile.toStdString(); - if (filePath != "") - { - PeersDialog::addAttachment(filePath); - } + QString file; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", file)) { + addAttachment(file.toUtf8().constData()); + } } void PeersDialog::addAttachment(std::string filePath) { @@ -1950,12 +1943,13 @@ bool PeersDialog::fileSave() bool PeersDialog::fileSaveAs() { - QString fn = QFileDialog::getSaveFileName(this, tr("Save as..."), - QString(), tr("Text File (*.txt );;All Files (*)")); - if (fn.isEmpty()) - return false; - setCurrentFileName(fn); - return fileSave(); + QString fn; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_HISTORY, tr("Save as..."), tr("Text File (*.txt );;All Files (*)"), fn)) { + setCurrentFileName(fn); + return fileSave(); + } + + return false; } void PeersDialog::setCurrentFileName(const QString &fileName) diff --git a/retroshare-gui/src/gui/PluginManagerWidget.cpp b/retroshare-gui/src/gui/PluginManagerWidget.cpp index 7e7b6274f..b017bf700 100644 --- a/retroshare-gui/src/gui/PluginManagerWidget.cpp +++ b/retroshare-gui/src/gui/PluginManagerWidget.cpp @@ -28,7 +28,6 @@ #include #include -#include #include #include diff --git a/retroshare-gui/src/gui/RSHumanReadableDelegate.h b/retroshare-gui/src/gui/RSHumanReadableDelegate.h index 944f7980f..08165b4a1 100644 --- a/retroshare-gui/src/gui/RSHumanReadableDelegate.h +++ b/retroshare-gui/src/gui/RSHumanReadableDelegate.h @@ -38,6 +38,7 @@ */ #include +#include #include class RSHumanReadableDelegate: public QAbstractItemDelegate diff --git a/retroshare-gui/src/gui/SearchDialog.cpp b/retroshare-gui/src/gui/SearchDialog.cpp index c926a39fc..57b919580 100644 --- a/retroshare-gui/src/gui/SearchDialog.cpp +++ b/retroshare-gui/src/gui/SearchDialog.cpp @@ -20,6 +20,7 @@ ****************************************************************/ #include +#include #include "SearchDialog.h" #include "RetroShareLink.h" diff --git a/retroshare-gui/src/gui/channels/CreateChannel.cpp b/retroshare-gui/src/gui/channels/CreateChannel.cpp index 4ddca74c1..f7acdfec1 100644 --- a/retroshare-gui/src/gui/channels/CreateChannel.cpp +++ b/retroshare-gui/src/gui/channels/CreateChannel.cpp @@ -21,7 +21,6 @@ #include #include -#include #include @@ -244,8 +243,8 @@ void CreateChannel::cancelChannel() void CreateChannel::addChannelLogo() { - QString fileName = QFileDialog::getOpenFileName(this, tr("Load File"), QDir::homePath(), tr("Pictures (*.png *.xpm *.jpg)")); - if(!fileName.isEmpty()) + QString fileName; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Load File"), tr("Pictures (*.png *.xpm *.jpg)"), fileName)) { picture = QPixmap(fileName).scaled(64,64, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); diff --git a/retroshare-gui/src/gui/channels/CreateChannelMsg.cpp b/retroshare-gui/src/gui/channels/CreateChannelMsg.cpp index 7879d3f61..79e73caed 100644 --- a/retroshare-gui/src/gui/channels/CreateChannelMsg.cpp +++ b/retroshare-gui/src/gui/channels/CreateChannelMsg.cpp @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -289,14 +288,15 @@ void CreateChannelMsg::addAttachment(const std::string &hash, const std::string void CreateChannelMsg::addExtraFile() { - /* add a SubFileItem to the attachment section */ - std::cerr << "CreateChannelMsg::addExtraFile() opening file dialog"; - std::cerr << std::endl; + /* add a SubFileItem to the attachment section */ + std::cerr << "CreateChannelMsg::addExtraFile() opening file dialog"; + std::cerr << std::endl; - // select a file - QStringList files = QFileDialog::getOpenFileNames(this, tr("Add Extra File"), "", "", 0, QFileDialog::DontResolveSymlinks); - for (QStringList::iterator fileIt = files.begin(); fileIt != files.end(); fileIt++) { - addAttachment((*fileIt).toUtf8().constData()); + QStringList files; + if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) { + for (QStringList::iterator fileIt = files.begin(); fileIt != files.end(); fileIt++) { + addAttachment((*fileIt).toUtf8().constData()); + } } } @@ -563,8 +563,8 @@ void CreateChannelMsg::sendMessage(std::wstring subject, std::wstring msg, std:: void CreateChannelMsg::addThumbnail() { - QString fileName = QFileDialog::getOpenFileName(this, tr("Load File"), QDir::homePath(), tr("Pictures (*.png *.xpm *.jpg)")); - if(!fileName.isEmpty()) + QString fileName; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Load File"), tr("Pictures (*.png *.xpm *.jpg)"), fileName)) { picture = QPixmap(fileName).scaled(156,107, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.cpp b/retroshare-gui/src/gui/chat/PopupChatDialog.cpp index 22e4f4af7..afd621843 100644 --- a/retroshare-gui/src/gui/chat/PopupChatDialog.cpp +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -37,6 +36,7 @@ #include "PopupChatDialog.h" #include "PopupChatWindow.h" #include "gui/RetroShareLink.h" +#include "util/misc.h" #include "rshare.h" #include @@ -889,26 +889,19 @@ void PopupChatDialog::updateAvatar() void PopupChatDialog::addExtraFile() { - // select a file - QString qfile = QFileDialog::getOpenFileName(this, tr("Add Extra File"), "", "", 0, - QFileDialog::DontResolveSymlinks); - std::string filePath = qfile.toStdString(); - if (filePath != "") - { - addAttachment(filePath,0); - } + QString file; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", file)) { + addAttachment(file.toUtf8().constData(), 0); + } } void PopupChatDialog::addExtraPicture() { - // select a picture file - QString qfile = QFileDialog::getOpenFileName(this, "Load Picture File", QDir::homePath(), "Pictures (*.png *.xpm *.jpg)",0, - QFileDialog::DontResolveSymlinks); - std::string filePath=qfile.toStdString(); - if(filePath!="") - { - PopupChatDialog::addAttachment(filePath,1); //picture - } + // select a picture file + QString file; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Load Picture File"), "Pictures (*.png *.xpm *.jpg)", file)) { + addAttachment(file.toUtf8().constData(), 1); + } } void PopupChatDialog::addAttachment(std::string filePath,int flag) @@ -1115,12 +1108,13 @@ bool PopupChatDialog::fileSave() bool PopupChatDialog::fileSaveAs() { - QString fn = QFileDialog::getSaveFileName(this, tr("Save as..."), - QString(), tr("Text File (*.txt );;All Files (*)")); - if (fn.isEmpty()) - return false; - setCurrentFileName(fn); - return fileSave(); + QString fn; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_HISTORY, tr("Save as..."), tr("Text File (*.txt );;All Files (*)"), fn)) { + setCurrentFileName(fn); + return fileSave(); + } + + return false; } void PopupChatDialog::setCurrentFileName(const QString &fileName) diff --git a/retroshare-gui/src/gui/chat/PopupChatWindow.cpp b/retroshare-gui/src/gui/chat/PopupChatWindow.cpp index 347968ba9..c7ba08f0d 100644 --- a/retroshare-gui/src/gui/chat/PopupChatWindow.cpp +++ b/retroshare-gui/src/gui/chat/PopupChatWindow.cpp @@ -21,13 +21,13 @@ ****************************************************************/ #include -#include #include "PopupChatWindow.h" #include "PopupChatDialog.h" #include "gui/settings/rsharesettings.h" #include "gui/settings/RsharePeerSettings.h" #include "gui/common/StatusDefs.h" +#include"util/misc.h" #include #include @@ -262,9 +262,9 @@ void PopupChatWindow::calculateTitle(PopupChatDialog *dialog) void PopupChatWindow::getAvatar() { - QString fileName = QFileDialog::getOpenFileName(this, "Load File", QDir::homePath(), "Pictures (*.png *.xpm *.jpg)"); - - if(!fileName.isEmpty()) { + QString fileName; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Load File"), tr("Pictures (*.png *.xpm *.jpg *.tiff *.gif)"), fileName)) + { QPixmap picture = QPixmap(fileName).scaled(96,96, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); std::cerr << "Sending avatar image down the pipe" << std::endl; diff --git a/retroshare-gui/src/gui/forums/CreateForumMsg.cpp b/retroshare-gui/src/gui/forums/CreateForumMsg.cpp index f4886635d..a3ed6cef8 100644 --- a/retroshare-gui/src/gui/forums/CreateForumMsg.cpp +++ b/retroshare-gui/src/gui/forums/CreateForumMsg.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -195,14 +194,12 @@ void CreateForumMsg::addSmileys() void CreateForumMsg::addFile() { - // select a file - QString qfile = QFileDialog::getOpenFileName(this, tr("Add Extra File"), "", "", 0, - QFileDialog::DontResolveSymlinks); - std::string filePath = qfile.toStdString(); - if (filePath != "") - { - CreateForumMsg::addAttachment(filePath); - } + QStringList files; + if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) { + for (QStringList::iterator fileIt = files.begin(); fileIt != files.end(); fileIt++) { + addAttachment((*fileIt).toUtf8().constData()); + } + } } void CreateForumMsg::addAttachment(std::string filePath) { @@ -236,21 +233,18 @@ void CreateForumMsg::fileHashingFinished(AttachFileItem* file) { return; } - //convert fileSize from uint_64 to string for html link - char fileSizeChar [100]; - sprintf(fileSizeChar, "%llu", (unsigned long long int)file->FileSize()); - std::string fileSize = *(&fileSizeChar); + RetroShareLink link(QString::fromUtf8(file->FileName().c_str()), file->FileSize(), QString::fromStdString(file->FileHash())); + if (link.valid()) { + QString mesgString = link.toHtmlSize() + "
"; - std::string mesgString = "" - + "retroshare://file|" + (file->FileName()) + "|" + fileSize + "|" + (file->FileHash()) + "" + "
"; #ifdef CHAT_DEBUG - std::cerr << "CreateForumMsg::anchorClicked mesgString : " << mesgString << std::endl; + std::cerr << "CreateForumMsg::anchorClicked mesgString : " << mesgString.toStdString() << std::endl; #endif - ui.forumMessage->textCursor().insertHtml(QString::fromStdString(mesgString)); - - ui.forumMessage->setFocus( Qt::OtherFocusReason ); + ui.forumMessage->textCursor().insertHtml(mesgString); + ui.forumMessage->setFocus( Qt::OtherFocusReason ); + } } void CreateForumMsg::dropEvent(QDropEvent *event) diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.cpp b/retroshare-gui/src/gui/msgs/MessageComposer.cpp index 522555b85..cf07a4d95 100644 --- a/retroshare-gui/src/gui/msgs/MessageComposer.cpp +++ b/retroshare-gui/src/gui/msgs/MessageComposer.cpp @@ -25,12 +25,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include @@ -1894,10 +1894,10 @@ void MessageComposer::fileNew() void MessageComposer::fileOpen() { - QString fn = QFileDialog::getOpenFileName(this, tr("Open File..."), - QString(), tr("HTML-Files (*.htm *.html);;All Files (*)")); - if (!fn.isEmpty()) + QString fn; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_MESSAGES, tr("Open File..."), tr("HTML-Files (*.htm *.html);;All Files (*)"), fn)) { load(fn); + } } bool MessageComposer::fileSave() @@ -1917,12 +1917,13 @@ bool MessageComposer::fileSave() bool MessageComposer::fileSaveAs() { - QString fn = QFileDialog::getSaveFileName(this, tr("Save as..."), - QString(), tr("HTML-Files (*.htm *.html);;All Files (*)")); - if (fn.isEmpty()) - return false; - setCurrentFileName(fn); - return fileSave(); + QString fn; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_MESSAGES, tr("Save as..."), tr("HTML-Files (*.htm *.html);;All Files (*)"), fn)) { + setCurrentFileName(fn); + return fileSave(); + } + + return false; } void MessageComposer::saveasDraft() @@ -1949,9 +1950,8 @@ void MessageComposer::filePrint() void MessageComposer::filePrintPdf() { #ifndef QT_NO_PRINTER - QString fileName = QFileDialog::getSaveFileName(this, "Export PDF", - QString(), "*.pdf"); - if (!fileName.isEmpty()) { + QString fileName; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_MESSAGES, tr("Export PDF"), "*.pdf", fileName)) { if (QFileInfo(fileName).suffix().isEmpty()) fileName.append(".pdf"); QPrinter printer(QPrinter::HighResolution); @@ -2024,19 +2024,15 @@ void MessageComposer::on_contactsdockWidget_visibilityChanged(bool visible) void MessageComposer::addImage() { - QString fileimg = QFileDialog::getOpenFileName( this, tr( "Choose Image" ), - QString(Settings->valueFromGroup("MessageComposer", "LastDir").toString()) ,tr("Image Files supported (*.png *.jpeg *.jpg *.gif)")); + QString fileimg; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Choose Image"), tr("Image Files supported (*.png *.jpeg *.jpg *.gif)"), fileimg)) { + QImage base(fileimg); - if ( fileimg.isEmpty() ) { - return; + QString pathimage = fileimg.left(fileimg.lastIndexOf("/"))+"/"; + Settings->setValueToGroup("MessageComposer", "LastDir", pathimage); + + Create_New_Image_Tag(fileimg); } - - QImage base(fileimg); - - QString pathimage = fileimg.left(fileimg.lastIndexOf("/"))+"/"; - Settings->setValueToGroup("MessageComposer", "LastDir", pathimage); - - Create_New_Image_Tag(fileimg); } void MessageComposer::Create_New_Image_Tag( const QString urlremoteorlocal ) @@ -2139,9 +2135,11 @@ void MessageComposer::addPostSplitter() void MessageComposer::attachFile() { // select a file - QStringList files = QFileDialog::getOpenFileNames(this, tr("Add Extra File"), "", "", 0, QFileDialog::DontResolveSymlinks); - for (QStringList::iterator fileIt = files.begin(); fileIt != files.end(); fileIt++) { - MessageComposer::addAttachment((*fileIt).toUtf8().constData()); + QStringList files; + if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) { + for (QStringList::iterator fileIt = files.begin(); fileIt != files.end(); fileIt++) { + addAttachment((*fileIt).toUtf8().constData()); + } } } diff --git a/retroshare-gui/src/gui/settings/CryptoPage.cpp b/retroshare-gui/src/gui/settings/CryptoPage.cpp index 5a89838db..9340f8187 100755 --- a/retroshare-gui/src/gui/settings/CryptoPage.cpp +++ b/retroshare-gui/src/gui/settings/CryptoPage.cpp @@ -21,11 +21,12 @@ #include #include -#include +#include #include #include #include "CryptoPage.h" +#include "util/misc.h" #include //for rsPeers variable @@ -115,12 +116,12 @@ bool CryptoPage::fileSave() bool CryptoPage::fileSaveAs() { - QString fn = QFileDialog::getSaveFileName(this, tr("Save as..."), - QString(), tr("RetroShare Certificate (*.rsc );;All Files (*)")); - if (fn.isEmpty()) - return false; - setCurrentFileName(fn); - return fileSave(); + QString fn; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_CERT, tr("Save as..."), tr("RetroShare Certificate (*.rsc );;All Files (*)"), fn)) { + setCurrentFileName(fn); + return fileSave(); + } + return false; } void CryptoPage::setCurrentFileName(const QString &fileName) diff --git a/retroshare-gui/src/gui/settings/rsharesettings.cpp b/retroshare-gui/src/gui/settings/rsharesettings.cpp index ccef1392b..0d10936c8 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.cpp +++ b/retroshare-gui/src/gui/settings/rsharesettings.cpp @@ -173,6 +173,45 @@ void RshareSettings::setSheetName(QString sheet) setValue(SETTING_SHEETNAME, sheet); } +static QString getKeyForLastDir(RshareSettings::enumLastDir type) +{ + switch (type) { + case RshareSettings::LASTDIR_EXTRAFILE: + return "ExtraFile"; + case RshareSettings::LASTDIR_CERT: + return "Certificate"; + case RshareSettings::LASTDIR_HISTORY: + return "History"; + case RshareSettings::LASTDIR_IMAGES: + return "Images"; + case RshareSettings::LASTDIR_MESSAGES: + return "Messages"; + case RshareSettings::LASTDIR_BLOGS: + return "Messages"; + } + return ""; +} + +QString RshareSettings::getLastDir(enumLastDir type) +{ + QString key = getKeyForLastDir(type); + if (key.isEmpty()) { + return ""; + } + + return valueFromGroup("LastDir", key).toString(); +} + +void RshareSettings::setLastDir(enumLastDir type, const QString &lastDir) +{ + QString key = getKeyForLastDir(type); + if (key.isEmpty()) { + return; + } + + setValueToGroup("LastDir", key, lastDir); +} + /** Returns the bandwidth line filter. */ uint RshareSettings::getBWGraphFilter() { diff --git a/retroshare-gui/src/gui/settings/rsharesettings.h b/retroshare-gui/src/gui/settings/rsharesettings.h index 49af523db..1c7618655 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.h +++ b/retroshare-gui/src/gui/settings/rsharesettings.h @@ -55,7 +55,17 @@ class QMainWindow; */ class RshareSettings : public RSettings { - +public: + enum enumLastDir + { + LASTDIR_EXTRAFILE, + LASTDIR_CERT, + LASTDIR_HISTORY, + LASTDIR_IMAGES, + LASTDIR_MESSAGES, + LASTDIR_BLOGS + }; + public: /* create settings object */ static void Create (); @@ -92,6 +102,9 @@ public: /** Set the destination log file. */ void setLogFile(QString file); + QString getLastDir(enumLastDir type); + void setLastDir(enumLastDir type, const QString &lastDir); + /* Get the bandwidth graph line filter. */ uint getBWGraphFilter(); /** Set the bandwidth graph line filter. */ diff --git a/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.cpp b/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.cpp index da72637a4..3798041af 100644 --- a/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.cpp +++ b/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.cpp @@ -20,10 +20,10 @@ ****************************************************************/ #include -#include #include #include "CreateBlog.h" +#include "util/misc.h" #include @@ -143,8 +143,8 @@ void CreateBlog::createBlog() void CreateBlog::addBlogLogo(){ - QString fileName = QFileDialog::getOpenFileName(this, "Load File", QDir::homePath(), "Pictures (*.png *.xpm *.jpg)"); - if(!fileName.isEmpty()) + QString fileName; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Load File"), tr("Pictures (*.png *.xpm *.jpg)"), fileName)) { picture = QPixmap(fileName).scaled(64,64, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); diff --git a/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.cpp b/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.cpp index ee65c73c2..3a1ff2959 100644 --- a/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.cpp +++ b/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -35,6 +35,7 @@ #include "CreateBlogMsg.h" #include "gui/msgs/textformat.h" +#include "util/misc.h" #include @@ -803,9 +804,8 @@ void CreateBlogMsg::fileNew() void CreateBlogMsg::fileOpen() { - QString fn = QFileDialog::getOpenFileName(this, tr("Open File..."), - QString(), tr("HTML-Files (*.htm *.html);;All Files (*)")); - if (!fn.isEmpty()) + QString fn; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_BLOGS, tr("Open File..."), tr("HTML-Files (*.htm *.html);;All Files (*)"), fn)) load(fn); } @@ -823,14 +823,15 @@ bool CreateBlogMsg::fileSave() bool CreateBlogMsg::fileSaveAs() { - QString fn = QFileDialog::getSaveFileName(this, tr("Save as..."), - QString(), tr("ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*)")); - if (fn.isEmpty()) - return false; - if (! (fn.endsWith(".odt", Qt::CaseInsensitive) || fn.endsWith(".htm", Qt::CaseInsensitive) || fn.endsWith(".html", Qt::CaseInsensitive)) ) - fn += ".odt"; // default - setCurrentFileName(fn); - return fileSave(); + QString fn; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_BLOGS, tr("Save as..."), tr("ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*)"), fn)) { + if (! (fn.endsWith(".odt", Qt::CaseInsensitive) || fn.endsWith(".htm", Qt::CaseInsensitive) || fn.endsWith(".html", Qt::CaseInsensitive)) ) + fn += ".odt"; // default + setCurrentFileName(fn); + return fileSave(); + } + + return false; } void CreateBlogMsg::filePrint() @@ -872,9 +873,8 @@ void CreateBlogMsg::filePrintPdf() { #ifndef QT_NO_PRINTER //! [0] - QString fileName = QFileDialog::getSaveFileName(this, "Export PDF", - QString(), "*.pdf"); - if (!fileName.isEmpty()) { + QString fileName; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_MESSAGES, tr("Export PDF"), "*.pdf", fileName)) { if (QFileInfo(fileName).suffix().isEmpty()) fileName.append(".pdf"); QPrinter printer(QPrinter::HighResolution); @@ -901,22 +901,14 @@ void CreateBlogMsg::setCurrentFileName(const QString &fileName) setWindowModified(false); } -void CreateBlogMsg::addImage() +void CreateBlogMsg::addImage() { - - QString fileimg = QFileDialog::getOpenFileName( this, tr( "Choose Image" ), - QString(setter.value("LastDir").toString()) ,tr("Image Files supported (*.png *.jpeg *.jpg *.gif)")); + QString fileimg; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_MESSAGES, tr("Choose Image"), tr("Image Files supported (*.png *.jpeg *.jpg *.gif)"), fileimg)) { + QImage base(fileimg); - if ( fileimg.isEmpty() ) { - return; + Create_New_Image_Tag(fileimg); } - - QImage base(fileimg); - - QString pathimage = fileimg.left(fileimg.lastIndexOf("/"))+"/"; - setter.setValue("LastDir",pathimage); - - Create_New_Image_Tag(fileimg); } void CreateBlogMsg::Create_New_Image_Tag( const QString urlremoteorlocal ) diff --git a/retroshare-gui/src/lang/retroshare_de.qm b/retroshare-gui/src/lang/retroshare_de.qm index 57abe5e7a5d4ffb677ebade3c502affb2992e081..bc0f523d12406d80db1b4e692f203a1e6611aed7 100644 GIT binary patch delta 15961 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�VH)sPtxiq$kX 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 add a Name Bitte Name hinzufügen + + + Load File + Lade Datei + + + + Pictures (*.png *.xpm *.jpg) + Bilder (*.png *.xpm *.jpg) + Authemticated Messages @@ -1876,7 +1886,7 @@ p, li { white-space: pre-wrap; } Rückgängig - + RetroShare @@ -2036,12 +2046,12 @@ Do you want to save your changes? Möchten Sie die Änderungen speichern? - + Open File... Datei öffnen... - + HTML-Files (*.htm *.html);;All Files (*) HTML-Dateien (*.htm *.html);;Alle Dateien (*) @@ -2051,22 +2061,27 @@ Möchten Sie die Änderungen speichern? Speichern unter... - + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) - + Print Document Dokument drucken - + + Export PDF + PDF exportieren + + + Choose Image Bild wählen - + Image Files supported (*.png *.jpeg *.jpg *.gif) Unterstützte Bilddateien (*.png *.jpeg *.jpg *.gif) @@ -2174,7 +2189,7 @@ Möchten Sie die Änderungen speichern? Erstellen - + RetroShare @@ -2184,7 +2199,7 @@ Möchten Sie die Änderungen speichern? Bitte einen Name hinzufügen - + Load File Lade Datei @@ -2285,12 +2300,12 @@ p, li { white-space: pre-wrap; } Drag'n'Drop Dateien aus den Suchergebnissen - + Add Extra File Zusätzlich eine Datei hinzufügen - + RetroShare @@ -2306,7 +2321,7 @@ p, li { white-space: pre-wrap; } Bitte Subjekt nicht vergessen - + Load File Lade Datei @@ -2436,7 +2451,7 @@ p, li { white-space: pre-wrap; } - + Paste RetroShare Link RetroShare Link einfügen @@ -2481,7 +2496,7 @@ p, li { white-space: pre-wrap; } Du kannst Dateien mit Drag'n'Drop anhängen - + Drop file error. Dateifehler bei Drag'n'Drop. @@ -2542,7 +2557,7 @@ p, li { white-space: pre-wrap; } CryptoPage - + RetroShare @@ -2552,12 +2567,12 @@ p, li { white-space: pre-wrap; } Dein öffentlicher Schlüssel ist in die Zwischenablage kopiert worden - + Save as... Speichern unter... - + RetroShare Certificate (*.rsc );;All Files (*) @@ -5827,18 +5842,18 @@ Möchtest Du die Nachricht in den Entwürfen speichern? &Format - + Open File... Datei öffnen... - + HTML-Files (*.htm *.html);;All Files (*) HTML-Dateien (*.htm *.html);;Alle Dateien (*) - + Save as... Speichern unter... @@ -5848,29 +5863,34 @@ Möchtest Du die Nachricht in den Entwürfen speichern? Dokument drucken - + + Export PDF + PDF exportieren + + + Message has not been Sent. Do you want to save message ? Nachricht noch nicht versandt. Willst Du die Nachricht speichern ? - + Choose Image Bild wählen - + Image Files supported (*.png *.jpeg *.jpg *.gif) Unterstützte Bilddateien (*.png *.jpeg *.jpg *.gif) - + Add Extra File Zusätzliche Datei hinzufügen - + Drop file error. Dateifehler bei Drag'n'Drop. @@ -5886,7 +5906,7 @@ Willst Du die Nachricht speichern ? Datei nicht gefunden oder Dateiname nicht akzeptiert. - + Friend Recommendation(s) Freundempfehlung(en) @@ -6372,7 +6392,7 @@ p, li { white-space: pre-wrap; } MessengerWindow - + Expand all Alle erweitern @@ -6587,37 +6607,27 @@ p, li { white-space: pre-wrap; } NetworkDialog - - Select a pem/pqi File - Wählen einer PEM- oder PQI-Datei + Wählen einer PEM- oder PQI-Datei - - File Not Found - Datei nicht gefunden + Datei nicht gefunden - - %1 does not exist. Would you like to create it? - %1 ist nicht vorhanden. Möchten Sie es jetzt erstellen? + %1 ist nicht vorhanden. Möchten Sie es jetzt erstellen? - - Failed to Create File - Es ist nicht gelungen, die Datei zu erstellen + Es ist nicht gelungen, die Datei zu erstellen - - Unable to create %1 [%2] - Kann %1 [%2] nicht erstellen + Kann %1 [%2] nicht erstellen - + Personal signature @@ -6654,14 +6664,12 @@ Right-click and select 'make friend' to be able to connect. Rechtsklick und als Freund hinzufügen um zu verbinden. - Select Certificate - Zertifikat auswählen + Zertifikat auswählen - Certificates (*.pqi *.pem) - Zertifikate (*.pqi *.pem) + Zertifikate (*.pqi *.pem) @@ -6772,7 +6780,7 @@ p, li { white-space: pre-wrap; } Leeren - + Deny friend Blockiere Freund @@ -6797,12 +6805,12 @@ p, li { white-space: pre-wrap; } Nachbar-Details... - + Unknown Unbekannt - + Authentication matrix Authentifizierungsmatrix @@ -6812,28 +6820,17 @@ p, li { white-space: pre-wrap; } Netzwerk Ansicht - + yourself selbst - - - - - RetroShare - - - - Certificate file successfully created - Zertifikat-Datei erfolgreich erstellt + Zertifikat-Datei erfolgreich erstellt - - Sorry, certificate file creation failed - Zertifikat-Datei konnte nicht erstellt werden + Zertifikat-Datei konnte nicht erstellt werden @@ -6889,19 +6886,16 @@ p, li { white-space: pre-wrap; } Peer ID - Sorry, create certificate failed - Zertifikat-Datei konnte nicht erstellt werden + Zertifikat-Datei konnte nicht erstellt werden - Please choose a filename - Bitte wählen sie einen Dateinamen + Bitte wählen sie einen Dateinamen - RetroShare Certificate (*.rsc );;All Files (*) - RetroShare Zertifikat (*.rsc );;Alle Dateien (*) + RetroShare Zertifikat (*.rsc );;Alle Dateien (*) @@ -7315,12 +7309,12 @@ p, li { white-space: pre-wrap; } Chat - + Save Certificate Zertifikat speichern - + Certificates (*.pqi) Zertifikate (*.pqi) @@ -7435,18 +7429,28 @@ p, li { white-space: pre-wrap; } Verfügbar - + New group chat Neuer Gruppenchat - + + Load File + Lade Datei + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + Bilder (*.png *.xpm *.jpg *.tiff *.gif) + + + Add Extra File Zusätzliche Datei hinzufügen - + Drop file error. Dateifehler bei Drag'n'Drop. @@ -7554,7 +7558,7 @@ p, li { white-space: pre-wrap; } - + Add Friend Freund hinzufügen @@ -7609,12 +7613,12 @@ p, li { white-space: pre-wrap; } - + RetroShare - + Message Group Gruppe anschreiben @@ -7629,17 +7633,17 @@ p, li { white-space: pre-wrap; } Gruppe entfernen - + Do you want to remove this Friend? Willst du diesen Freund entfernen? - + Save as... Speichern unter... - + Text File (*.txt );;All Files (*) Text Datei (*.txt );;Alle Dateien (*) @@ -7667,12 +7671,12 @@ p, li { white-space: pre-wrap; } Status Spalte ausblenden - + Friends Storm Aktivitäten - + is typing... tippt... @@ -7692,7 +7696,7 @@ p, li { white-space: pre-wrap; } Freunde - + Paste Friend Link RetroShare Link einfügen @@ -7969,7 +7973,7 @@ p, li { white-space: pre-wrap; } PluginFrame - + Remove Entfernen @@ -8005,12 +8009,17 @@ p, li { white-space: pre-wrap; } Avatar zeigen - + + Load Picture File + Lade Bilddatei + + + File not found or file name not accepted. Datei nicht gefunden oder Dateiname nicht akzeptiert. - + Messages you send will be delivered after Friend is again Online Nachrichten, die Du versendest gehen bei diesem Freund erst wieder ein wenn er Online ist @@ -8078,12 +8087,12 @@ p, li { white-space: pre-wrap; } Durchgestrichen - + Add Extra File Zusätzlich eine Datei hinzufügen - + Drop file error. Dateifehler bei Drag'n'Drop. @@ -8105,17 +8114,17 @@ p, li { white-space: pre-wrap; } Chat Verlauf speichern - + Save as... Speichern unter... - + Text File (*.txt );;All Files (*) Text Datei (*.txt );;Alle Dateien (*) - + Your Friend is offline Do you want to send them a Message instead Dein Freund ist Offline willst du ihm stattdessen eine Nachricht senden @@ -8126,7 +8135,7 @@ Do you want to send them a Message instead Bild anhängen - + is Idle and may not reply antwortet möglicherweise nicht, da der Status auf "Untätig" gesetzt wurde @@ -8146,7 +8155,7 @@ Do you want to send them a Message instead ist Offline. - + Paste RetroShare Link RetroShare Link einfügen @@ -8195,6 +8204,16 @@ Do you want to send them a Message instead RetroShare RetroShare + + + Load File + Lade Datei + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + Bilder (*.png *.xpm *.jpg *.tiff *.gif) + PrintPreview @@ -8336,7 +8355,7 @@ Do you want to send them a Message instead ProfileView - + Clear Photo Photo entfernen @@ -8743,17 +8762,17 @@ p, li { white-space: pre-wrap; } Deny friend - Blockiere Freund + Blockiere Freund Make friend - Freund hinzufügen + Freund hinzufügen Peer details - Nachbar Details + Nachbar Details @@ -9281,7 +9300,7 @@ p, li { white-space: pre-wrap; } - + Download Herunterladen @@ -10694,7 +10713,7 @@ p, li { white-space: pre-wrap; } - + Play File Datei abspielen @@ -11473,7 +11492,7 @@ p, li { white-space: pre-wrap; } misc - + Unknown Unknown (size) Unbekannt @@ -11509,7 +11528,7 @@ p, li { white-space: pre-wrap; } - + Unknown Unbekannt diff --git a/retroshare-gui/src/util/misc.cpp b/retroshare-gui/src/util/misc.cpp new file mode 100644 index 000000000..cebdd56cb --- /dev/null +++ b/retroshare-gui/src/util/misc.cpp @@ -0,0 +1,286 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, defnax + * Copyright (C) 2006 Christophe Dumez + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + *************************************************************************/ + +#include +#include +#include + +#include "misc.h" + +// return best userfriendly storage unit (B, KiB, MiB, GiB, TiB) +// use Binary prefix standards from IEC 60027-2 +// see http://en.wikipedia.org/wiki/Kilobyte +// value must be given in bytes +QString misc::friendlyUnit(float val) +{ + if(val < 0) { + return tr("Unknown", "Unknown (size)"); + } + const QString units[4] = {tr(" B", "bytes"), tr(" KiB", "kibibytes (1024 bytes)"), tr(" MiB", "mebibytes (1024 kibibytes)"), tr(" GiB", "gibibytes (1024 mibibytes)")}; + for(unsigned int i=0; i<5; ++i) { + if (val < 1024.) { + return QString(QByteArray::number(val, 'f', 1)) + units[i]; + } + val /= 1024.; + } + return QString(QByteArray::number(val, 'f', 1)) + tr(" TiB", "tebibytes (1024 gibibytes)"); +} + +bool misc::isPreviewable(QString extension) +{ + extension = extension.toUpper(); + if(extension == "AVI") return true; + if(extension == "MP3") return true; + if(extension == "OGG") return true; + if(extension == "OGM") return true; + if(extension == "WMV") return true; + if(extension == "WMA") return true; + if(extension == "MPEG") return true; + if(extension == "MPG") return true; + if(extension == "ASF") return true; + if(extension == "QT") return true; + if(extension == "RM") return true; + if(extension == "RMVB") return true; + if(extension == "RMV") return true; + if(extension == "SWF") return true; + if(extension == "FLV") return true; + if(extension == "WAV") return true; + if(extension == "MOV") return true; + if(extension == "VOB") return true; + if(extension == "MID") return true; + if(extension == "AC3") return true; + if(extension == "MP4") return true; + if(extension == "MP2") return true; + if(extension == "AVI") return true; + if(extension == "FLAC") return true; + if(extension == "AU") return true; + if(extension == "MPE") return true; + if(extension == "MOV") return true; + if(extension == "MKV") return true; + if(extension == "AIF") return true; + if(extension == "AIFF") return true; + if(extension == "AIFC") return true; + if(extension == "RA") return true; + if(extension == "RAM") return true; + if(extension == "M4P") return true; + if(extension == "M4A") return true; + if(extension == "3GP") return true; + if(extension == "AAC") return true; + if(extension == "SWA") return true; + if(extension == "MPC") return true; + if(extension == "MPP") return true; + return false; +} + +// return qBittorrent config path +QString misc::qBittorrentPath() +{ + QString qBtPath = QDir::homePath()+QDir::separator()+QString::fromUtf8(".qbittorrent") + QDir::separator(); + // Create dir if it does not exist + if(!QFile::exists(qBtPath)){ + QDir dir(qBtPath); + dir.mkpath(qBtPath); + } + return qBtPath; +} + +QString misc::findFileInDir(QString dir_path, QString fileName) +{ + QDir dir(dir_path); + if(dir.exists(fileName)) { + return dir.filePath(fileName); + } + QStringList subDirs = dir.entryList(QDir::Dirs); + QString subdir_name; + foreach(subdir_name, subDirs) { + QString result = findFileInDir(dir.path()+QDir::separator()+subdir_name, fileName); + if(!result.isNull()) { + return result; + } + } + return QString(); +} + +// Can't use template class for QString because >,< use unicode code for sorting +// which is not what a human would expect when sorting strings. +void misc::insertSortString(QList > &list, QPair value, Qt::SortOrder sortOrder) +{ + int i = 0; + if(sortOrder == Qt::AscendingOrder) { + while(i < list.size() and QString::localeAwareCompare(value.second, list.at(i).second) > 0) { + ++i; + } + }else{ + while(i < list.size() and QString::localeAwareCompare(value.second, list.at(i).second) < 0) { + ++i; + } + } + list.insert(i, value); +} + +float misc::getPluginVersion(QString filePath) +{ + QFile plugin(filePath); + if(!plugin.exists()){ + qDebug("%s plugin does not exist, returning 0.0", filePath.toUtf8().data()); + return 0.0; + } + if(!plugin.open(QIODevice::ReadOnly | QIODevice::Text)){ + return 0.0; + } + float version = 0.0; + while (!plugin.atEnd()){ + QByteArray line = plugin.readLine(); + if(line.startsWith("#VERSION: ")){ + line = line.split(' ').last(); + line.replace("\n", ""); + version = line.toFloat(); + qDebug("plugin %s version: %.2f", filePath.toUtf8().data(), version); + break; + } + } + return version; +} + +// Take a number of seconds and return an user-friendly +// time duration like "1d 2h 10m". +QString misc::userFriendlyDuration(qlonglong seconds) +{ + if(seconds < 0) { + return tr("Unknown"); + } + if(seconds < 60) { + return tr("< 1m", "< 1 minute"); + } + int minutes = seconds / 60; + if(minutes < 60) { + return tr("%1 minutes","e.g: 10minutes").arg(QString::QString::fromUtf8(misc::toString(minutes).c_str())); + } + int hours = minutes / 60; + minutes = minutes - hours*60; + if(hours < 24) { + return tr("%1h %2m", "e.g: 3hours 5minutes").arg(QString::fromUtf8(misc::toString(hours).c_str())).arg(QString::fromUtf8(misc::toString(minutes).c_str())); + } + int days = hours / 24; + hours = hours - days * 24; + if(days < 365) { + return tr("%1d %2h", "e.g: 2days 10hours").arg(QString::fromUtf8(misc::toString(days).c_str())).arg(QString::fromUtf8(misc::toString(hours).c_str())); + } + int years = days / 365; + days = days - years * 365; + return tr("%1y %2d", "e.g: 2 years 2days ").arg(QString::fromUtf8(misc::toString(years).c_str())).arg(QString::fromUtf8(misc::toString(days).c_str())); +} + +QString misc::userFriendlyUnit(double count, unsigned int decimal, double factor) +{ + if (count <= 0.0) { + return "0"; + } + + QString output; + + int i; + for (i = 0; i < 5; i++) { + if (count < factor) { + break; + } + + count /= factor; + } + + QString unit; + switch (i) { + case 0: + decimal = 0; // no decimal + break; + case 1: + unit = tr("k", "e.g: 3.1 k"); + break; + case 2: + unit = tr("M", "e.g: 3.1 M"); + break; + case 3: + unit = tr("G", "e.g: 3.1 G"); + break; + default: // >= 4 + unit = tr("T", "e.g: 3.1 T"); + } + + return QString("%1 %2").arg(count, 0, 'f', decimal).arg(unit); +} + +QString misc::removeNewLine(const QString &text) +{ + return QString(text).replace("\n", " "); +} + +QString misc::removeNewLine(const std::string &text) +{ + return QString::fromUtf8(text.c_str()).replace("\n", " "); +} + +QString misc::removeNewLine(const std::wstring &text) +{ + return QString::fromStdWString(text).replace("\n", " "); +} + +bool misc::getOpenFileName(QWidget *parent, RshareSettings::enumLastDir type, const QString &caption, const QString &filter, QString &file) +{ + QString lastDir = Settings->getLastDir(type); + + file = QFileDialog::getOpenFileName(parent, caption, lastDir, filter, NULL, QFileDialog::DontResolveSymlinks); + + if (file.isEmpty() == false) { + lastDir = QFileInfo(file).absoluteDir().absolutePath(); + Settings->setLastDir(type, lastDir); + } + + return !file.isEmpty(); +} + +bool misc::getOpenFileNames(QWidget *parent, RshareSettings::enumLastDir type, const QString &caption, const QString &filter, QStringList &files) +{ + QString lastDir = Settings->getLastDir(type); + + files = QFileDialog::getOpenFileNames(parent, caption, lastDir, filter, NULL, QFileDialog::DontResolveSymlinks); + + if (files.isEmpty() == false) { + lastDir = QFileInfo(*files.begin()).absoluteDir().absolutePath(); + Settings->setLastDir(type, lastDir); + } + + return !files.isEmpty(); +} + +bool misc::getSaveFileName(QWidget *parent, RshareSettings::enumLastDir type, const QString &caption, const QString &filter, QString &file) +{ + QString lastDir = Settings->getLastDir(type); + + file = QFileDialog::getSaveFileName(parent, caption, lastDir, filter); + + if (file.isEmpty() == false) { + lastDir = QFileInfo(file).absoluteDir().absolutePath(); + Settings->setLastDir(type, lastDir); + } + + return !file.isEmpty(); +} diff --git a/retroshare-gui/src/util/misc.h b/retroshare-gui/src/util/misc.h index 850990e3d..16707e5d6 100644 --- a/retroshare-gui/src/util/misc.h +++ b/retroshare-gui/src/util/misc.h @@ -26,29 +26,17 @@ #include #include #include -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include - - +#include "gui/settings/rsharesettings.h" /* Miscellaneaous functions that can be useful */ -class misc : public QObject{ - Q_OBJECT +class misc : public QObject +{ + Q_OBJECT - public: + public: // Convert any type of variable to C++ String // convert=true will convert -1 to 0 template static std::string toString(const T& x, bool convert=false) { @@ -113,272 +101,65 @@ class misc : public QObject{ // use Binary prefix standards from IEC 60027-2 // see http://en.wikipedia.org/wiki/Kilobyte // value must be given in bytes - static QString friendlyUnit(float val) { - if(val < 0) { - return tr("Unknown", "Unknown (size)"); - } - const QString units[4] = {tr(" B", "bytes"), tr(" KiB", "kibibytes (1024 bytes)"), tr(" MiB", "mebibytes (1024 kibibytes)"), tr(" GiB", "gibibytes (1024 mibibytes)")}; - for(unsigned int i=0; i<5; ++i) { - if (val < 1024.) { - return QString(QByteArray::number(val, 'f', 1)) + units[i]; - } - val /= 1024.; - } - return QString(QByteArray::number(val, 'f', 1)) + tr(" TiB", "tebibytes (1024 gibibytes)"); - } + static QString friendlyUnit(float val); - static bool isPreviewable(QString extension){ - extension = extension.toUpper(); - if(extension == "AVI") return true; - if(extension == "MP3") return true; - if(extension == "OGG") return true; - if(extension == "OGM") return true; - if(extension == "WMV") return true; - if(extension == "WMA") return true; - if(extension == "MPEG") return true; - if(extension == "MPG") return true; - if(extension == "ASF") return true; - if(extension == "QT") return true; - if(extension == "RM") return true; - if(extension == "RMVB") return true; - if(extension == "RMV") return true; - if(extension == "SWF") return true; - if(extension == "FLV") return true; - if(extension == "WAV") return true; - if(extension == "MOV") return true; - if(extension == "VOB") return true; - if(extension == "MID") return true; - if(extension == "AC3") return true; - if(extension == "MP4") return true; - if(extension == "MP2") return true; - if(extension == "AVI") return true; - if(extension == "FLAC") return true; - if(extension == "AU") return true; - if(extension == "MPE") return true; - if(extension == "MOV") return true; - if(extension == "MKV") return true; - if(extension == "AIF") return true; - if(extension == "AIFF") return true; - if(extension == "AIFC") return true; - if(extension == "RA") return true; - if(extension == "RAM") return true; - if(extension == "M4P") return true; - if(extension == "M4A") return true; - if(extension == "3GP") return true; - if(extension == "AAC") return true; - if(extension == "SWA") return true; - if(extension == "MPC") return true; - if(extension == "MPP") return true; - return false; - } + static bool isPreviewable(QString extension); // return qBittorrent config path - static QString qBittorrentPath() { - QString qBtPath = QDir::homePath()+QDir::separator()+QString::fromUtf8(".qbittorrent") + QDir::separator(); - // Create dir if it does not exist - if(!QFile::exists(qBtPath)){ - QDir dir(qBtPath); - dir.mkpath(qBtPath); - } - return qBtPath; - } - -// Not used anymore because it is not safe -// static bool removePath(QString path) { -// qDebug((QString::fromUtf8("file to delete:") + path).toUtf8()); -// if(!QFile::remove(path)) { -// // Probably a folder -// QDir current_dir(path); -// if(current_dir.exists()) { -// //Remove sub items -// QStringList subItems = current_dir.entryList(); -// QString item; -// foreach(item, subItems) { -// if(item != QString::fromUtf8(".") && item != QString::fromUtf8("..")) { -// qDebug("-> Removing "+(path+QDir::separator()+item).toUtf8()); -// removePath(path+QDir::separator()+item); -// } -// } -// // Remove empty folder -// if(current_dir.rmdir(path)) { -// return true; -// }else{ -// return false; -// } -// }else{ -// return false; -// } -// } -// return true; -// } - - static QString findFileInDir(QString dir_path, QString fileName) { - QDir dir(dir_path); - if(dir.exists(fileName)) { - return dir.filePath(fileName); - } - QStringList subDirs = dir.entryList(QDir::Dirs); - QString subdir_name; - foreach(subdir_name, subDirs) { - QString result = findFileInDir(dir.path()+QDir::separator()+subdir_name, fileName); - if(!result.isNull()) { - return result; - } - } - return QString(); - } + static QString qBittorrentPath(); + static QString findFileInDir(QString dir_path, QString fileName); // Insertion sort, used instead of bubble sort because it is // approx. 5 times faster. - template static void insertSort(QList > &list, const QPair& value, Qt::SortOrder sortOrder) { - int i = 0; - if(sortOrder == Qt::AscendingOrder) { - while(i < list.size() and value.second > list.at(i).second) { - ++i; - } - }else{ - while(i < list.size() and value.second < list.at(i).second) { - ++i; - } - } - list.insert(i, value); - } +// template static void insertSort(QList > &list, const QPair& value, Qt::SortOrder sortOrder) { +// int i = 0; +// if(sortOrder == Qt::AscendingOrder) { +// while(i < list.size() and value.second > list.at(i).second) { +// ++i; +// } +// }else{ +// while(i < list.size() and value.second < list.at(i).second) { +// ++i; +// } +// } +// list.insert(i, value); +// } - template static void insertSort2(QList > &list, const QPair& value, Qt::SortOrder sortOrder) { - int i = 0; - if(sortOrder == Qt::AscendingOrder) { - while(i < list.size() and value.first > list.at(i).first) { - ++i; - } - }else{ - while(i < list.size() and value.first < list.at(i).first) { - ++i; - } - } - list.insert(i, value); - } +// template static void insertSort2(QList > &list, const QPair& value, Qt::SortOrder sortOrder) { +// int i = 0; +// if(sortOrder == Qt::AscendingOrder) { +// while(i < list.size() and value.first > list.at(i).first) { +// ++i; +// } +// }else{ +// while(i < list.size() and value.first < list.at(i).first) { +// ++i; +// } +// } +// list.insert(i, value); +// } // Can't use template class for QString because >,< use unicode code for sorting // which is not what a human would expect when sorting strings. - static void insertSortString(QList > &list, QPair value, Qt::SortOrder sortOrder) { - int i = 0; - if(sortOrder == Qt::AscendingOrder) { - while(i < list.size() and QString::localeAwareCompare(value.second, list.at(i).second) > 0) { - ++i; - } - }else{ - while(i < list.size() and QString::localeAwareCompare(value.second, list.at(i).second) < 0) { - ++i; - } - } - list.insert(i, value); - } + static void insertSortString(QList > &list, QPair value, Qt::SortOrder sortOrder); - static float getPluginVersion(QString filePath) { - QFile plugin(filePath); - if(!plugin.exists()){ - qDebug("%s plugin does not exist, returning 0.0", filePath.toUtf8().data()); - return 0.0; - } - if(!plugin.open(QIODevice::ReadOnly | QIODevice::Text)){ - return 0.0; - } - float version = 0.0; - while (!plugin.atEnd()){ - QByteArray line = plugin.readLine(); - if(line.startsWith("#VERSION: ")){ - line = line.split(' ').last(); - line.replace("\n", ""); - version = line.toFloat(); - qDebug("plugin %s version: %.2f", filePath.toUtf8().data(), version); - break; - } - } - return version; - } + static float getPluginVersion(QString filePath); // Take a number of seconds and return an user-friendly // time duration like "1d 2h 10m". - static QString userFriendlyDuration(qlonglong seconds) - { - if(seconds < 0) { - return tr("Unknown"); - } - if(seconds < 60) { - return tr("< 1m", "< 1 minute"); - } - int minutes = seconds / 60; - if(minutes < 60) { - return tr("%1 minutes","e.g: 10minutes").arg(QString::QString::fromUtf8(misc::toString(minutes).c_str())); - } - int hours = minutes / 60; - minutes = minutes - hours*60; - if(hours < 24) { - return tr("%1h %2m", "e.g: 3hours 5minutes").arg(QString::fromUtf8(misc::toString(hours).c_str())).arg(QString::fromUtf8(misc::toString(minutes).c_str())); - } - int days = hours / 24; - hours = hours - days * 24; - if(days < 365) { - return tr("%1d %2h", "e.g: 2days 10hours").arg(QString::fromUtf8(misc::toString(days).c_str())).arg(QString::fromUtf8(misc::toString(hours).c_str())); - } - int years = days / 365; - days = days - years * 365; - return tr("%1y %2d", "e.g: 2 years 2days ").arg(QString::fromUtf8(misc::toString(years).c_str())).arg(QString::fromUtf8(misc::toString(days).c_str())); - } + static QString userFriendlyDuration(qlonglong seconds); - static QString userFriendlyUnit(double count, unsigned int decimal, double factor = 1000) - { - if (count <= 0.0) { - return "0"; - } + static QString userFriendlyUnit(double count, unsigned int decimal, double factor = 1000); - QString output; + static QString removeNewLine(const QString &text); + static QString removeNewLine(const std::string &text); + static QString removeNewLine(const std::wstring &text); - int i; - for (i = 0; i < 5; i++) { - if (count < factor) { - break; - } + static bool getOpenFileName(QWidget *parent, RshareSettings::enumLastDir type, const QString &caption, const QString &filter, QString &file); + static bool getOpenFileNames(QWidget *parent, RshareSettings::enumLastDir type, const QString &caption, const QString &filter, QStringList &files); - count /= factor; - } - - QString unit; - switch (i) { - case 0: - decimal = 0; // no decimal - break; - case 1: - unit = tr("k", "e.g: 3.1 k"); - break; - case 2: - unit = tr("M", "e.g: 3.1 M"); - break; - case 3: - unit = tr("G", "e.g: 3.1 G"); - break; - default: // >= 4 - unit = tr("T", "e.g: 3.1 T"); - } - - return QString("%1 %2").arg(count, 0, 'f', decimal).arg(unit); - } - - static QString removeNewLine(const QString &text) - { - return QString(text).replace("\n", " "); - } - - static QString removeNewLine(const std::string &text) - { - return QString::fromUtf8(text.c_str()).replace("\n", " "); - } - - static QString removeNewLine(const std::wstring &text) - { - return QString::fromStdWString(text).replace("\n", " "); - } + static bool getSaveFileName(QWidget *parent, RshareSettings::enumLastDir type, const QString &caption, const QString &filter, QString &file); }; // Trick to get a portable sleep() function