diff --git a/.travis.yml b/.travis.yml index 1f5333843b..841d2ef652 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,14 +3,24 @@ sudo: required language: cpp env: - - BUILD_VERSION="" - - BUILD_VERSION="disable_autoupdate" - - BUILD_VERSION="disable_register_custom_scheme" - - BUILD_VERSION="disable_crash_reports" - - BUILD_VERSION="disable_network_proxy" - - BUILD_VERSION="disable_desktop_file_generation" + global: + # GitHub auth token (GH_AUTH_TOKEN) + - secure: "QBbD9VXAx3Mn0vFmHZtm6/sq+twMyR7ilQh7TQm8gBy2TrjhHKDKQ4wRQ5sa2MUFUbzrUOvPlPGq1WuY1mAUt8UE6jZDJNyyDWb6iIlcEmNRsd39XAhYHvJ+uI9JsD+U3OctZ+7Bo4fno0RLv1D5lzh5bpohmjgWxx9TiSZItbsRU+m0XM0Tahx335aXF8NFoVjheGXCOcLAXDt6OmaKPmlrXreuta5nOoRKeOg5vHlt/KNU1pYb8MFvWJc14DKxq3jNqrYlo9vHFv5tVhR1aqvVFWTD/4Z88OSxx3POzyVWdMso0lFov9uxs8qHoqLsGhDMElggyz/jnqZIHpwQMaYIGQ0LLYDv21jGgOuCOWKYlfjDY+tuESXmVPzerTlYBWLZDPrpE8BnXVYo8B/sF4WN6oCuBRjawlqYhqTH+tDDORc9Uc9pamhcuh6OsLMx3PHoyg8joN3t8yUnwhySXyfQ36hqlZ+Y4bBDRZBH/SB/EPmedyLGwdhzQFsUnOBotYeOym7LUdnGraGcj1iTPLdo5TMlBYlAiB12J5mHTNuzUKXh+PBV4REg4Mm2xYX+Pue5Qo1JcOWJteIX4BdPv526DXB3yaNWS1pZgGvYqtBwQlCeOfwOYupS0PksvmV7aX7c4qJSyW3dmEd03cxmebD0b2SbqyPxGFuUajJ7B60=" + matrix: + - BUILD_VERSION="" + - BUILD_VERSION="disable_autoupdate" + - BUILD_VERSION="disable_register_custom_scheme" + - BUILD_VERSION="disable_crash_reports" + - BUILD_VERSION="disable_network_proxy" + - BUILD_VERSION="disable_desktop_file_generation" + - BUILD_VERSION="disable_unity_integration" + +matrix: + fast_finish: true arch: + repos: + - home_ItachiSan_archlinux_Arch_Extra=http://download.opensuse.org/repositories/home:/ItachiSan:/archlinux/Arch_Extra/$arch packages: - bzr - wget @@ -18,7 +28,7 @@ arch: - git - patch - - dee-fixed + - home_ItachiSan_archlinux_Arch_Extra/dee # Use fixed dee version (See #2005) - libunity - libappindicator-gtk2 diff --git a/.travis/build.sh b/.travis/build.sh index b31262833d..6e0a0ae0d8 100755 --- a/.travis/build.sh +++ b/.travis/build.sh @@ -83,6 +83,10 @@ prepare() { options+="\nDEFINES += TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION" fi + if [[ $BUILD_VERSION == *"disable_unity_integration"* ]]; then + options+="\nDEFINES += TDESKTOP_DISABLE_UNITY_INTEGRATION" + fi + options+='\nINCLUDEPATH += "/usr/lib/glib-2.0/include"' options+='\nINCLUDEPATH += "/usr/lib/gtk-2.0/include"' options+='\nINCLUDEPATH += "/usr/include/opus"' @@ -104,7 +108,7 @@ build() { cd "$srcdir/Libraries/qt${_qtver}" ./configure -prefix "$srcdir/qt" -release -opensource -confirm-license -qt-zlib \ -qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb \ - -qt-xkbcommon-x11 -no-opengl -static -nomake examples -nomake tests + -qt-xkbcommon-x11 -no-opengl -no-gtkstyle -static -nomake examples -nomake tests make --silent -j4 make --silent -j4 install diff --git a/.travis/check.sh b/.travis/check.sh index 3fe7c7fd3c..2aaae04719 100755 --- a/.travis/check.sh +++ b/.travis/check.sh @@ -13,6 +13,7 @@ checkCommitMessage() { if [[ $TRAVIS_COMMIT_MSG != *"Signed-off-by: "* ]];then error_msg "The commit message does not contain the signature!" error_msg "More information: https://github.com/telegramdesktop/tdesktop/blob/master/.github/CONTRIBUTING.md#sign-your-work" + addMissingSignatureInfos exit 1 else success_msg "Commit message contains signature" @@ -20,6 +21,37 @@ checkCommitMessage() { fi } +addMissingSignatureInfos() { + if [[ $BUILD_VERSION == "" ]]; then + local TEXT="Hi,\n\ +thanks for the pull request!\n\ +\n\ +Please read our [contributing policy](https://github.com/telegramdesktop/tdesktop/blob/master/.github/CONTRIBUTING.md). You'll need to make a pull request with the \\\"Signed-off-by:\\\" signature being the last line of your commit message, like it is described in [sign your work](https://github.com/telegramdesktop/tdesktop/blob/master/.github/CONTRIBUTING.md#sign-your-work) section. That will grant your work into the public domain.\n\ +\n\ +(See [travis build](https://travis-ci.org/telegramdesktop/tdesktop/jobs/${TRAVIS_JOB_ID}))" + addCommentToGitHub "${TEXT}" + addLabelToGitHub "missing signature" + info_msg "Added missing signature info on github" + fi +} + +addCommentToGitHub() { + local BODY=$1 + sendGitHubRequest "POST" "{\"body\": \"${BODY}\"}" "repos/${TRAVIS_REPO_SLUG}/issues/${TRAVIS_PULL_REQUEST}/comments" +} + +addLabelToGitHub() { + local LABEL=$1 + sendGitHubRequest "PATCH" "{\"labels\": [\"${LABEL}\"]}" "repos/${TRAVIS_REPO_SLUG}/issues/${TRAVIS_PULL_REQUEST}" +} + +sendGitHubRequest() { + local METHOD=$1 + local BODY=$2 + local URI=$3 + curl -H "Authorization: token ${GH_AUTH_TOKEN}" --request "${METHOD}" --data "${BODY}" --silent "https://api.github.com/${URI}" > /dev/null +} + source ./.travis/common.sh run diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index 4ffa156ac6..9bdb14fdf8 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -27,8 +27,6 @@ class MainWindow; class MainWidget; class SettingsWidget; class ApiWrap; -class Font; -class Color; class FileUploader; #include "history.h" diff --git a/Telegram/SourceFiles/layout.cpp b/Telegram/SourceFiles/layout.cpp index 54a7d259dd..2dcd973d7b 100644 --- a/Telegram/SourceFiles/layout.cpp +++ b/Telegram/SourceFiles/layout.cpp @@ -215,3 +215,23 @@ style::sprite documentCorner(int32 colorIndex) { RoundCorners documentCorners(int32 colorIndex) { return RoundCorners(DocBlueCorners + (colorIndex & 3)); } + +bool documentIsValidMediaFile(const QString &filepath) { + static StaticNeverFreedPointer> validMediaTypes(([] { + std_::unique_ptr> result = std_::make_unique>(); + *result = qsl("\ +webm mkv flv vob ogv ogg drc gif gifv mng avi mov qt wmv yuv rm rmvb asf amv mp4 m4p \ +m4v mpg mp2 mpeg mpe mpv m2v svi 3gp 3g2 mxf roq nsv f4v f4p f4a f4b wma divx evo mk3d \ +mka mks mcf m2p ps ts m2ts ifo aaf avchd cam dat dsh dvr-ms m1v fla flr sol wrap smi swf \ +wtv 8svx 16svx iff aiff aif aifc au bwf cdda raw wav flac la pac m4a ape ofr ofs off rka \ +shn tak tta wv brstm dts dtshd dtsma ast amr mp3 spx gsm aac mpc vqf ra ots swa vox voc \ +dwd smp aup cust mid mus sib sid ly gym vgm psf nsf mod ptb s3m xm it mt2 minipsf psflib \ +2sf dsf gsf psf2 qsf ssf usf rmj spc niff mxl xml txm ym jam mp1 mscz \ +").split(' '); + return result.release(); + })()); + + QFileInfo info(filepath); + auto parts = info.fileName().split('.', QString::SkipEmptyParts); + return !parts.isEmpty() && (validMediaTypes->indexOf(parts.back().toLower()) >= 0); +} diff --git a/Telegram/SourceFiles/layout.h b/Telegram/SourceFiles/layout.h index 1dddc2a3c9..6aa64f268c 100644 --- a/Telegram/SourceFiles/layout.h +++ b/Telegram/SourceFiles/layout.h @@ -83,6 +83,7 @@ style::color documentOverColor(int32 colorIndex); style::color documentSelectedColor(int32 colorIndex); style::sprite documentCorner(int32 colorIndex); RoundCorners documentCorners(int32 colorIndex); +bool documentIsValidMediaFile(const QString &filepath); class PaintContextBase { public: diff --git a/Telegram/SourceFiles/main.cpp b/Telegram/SourceFiles/main.cpp index e010502d5d..3fc2ce67ad 100644 --- a/Telegram/SourceFiles/main.cpp +++ b/Telegram/SourceFiles/main.cpp @@ -44,21 +44,9 @@ int main(int argc, char *argv[]) { Logs::start(); // must be started before Platform is started Platform::start(); // must be started before QApplication is created - // prepare fake args to disable QT_STYLE_OVERRIDE env variable - // currently this is required in some desktop environments, including Xubuntu 15.10 - // when we don't default style to "none" Qt dynamically loads GTK somehow internally and - // our own GTK dynamic load and usage leads GTK errors and freeze of the current main thread - // we can't disable our own GTK loading because it is required by libappindicator, which - // provides the tray icon for this system, because Qt tray icon is broken there - // see https://github.com/telegramdesktop/tdesktop/issues/1774 - QByteArray args[] = { "-style=0" }; - static const int a_cnt = sizeof(args) / sizeof(args[0]); - int a_argc = a_cnt + 1; - char *a_argv[a_cnt + 1] = { argv[0], args[0].data() }; - int result = 0; { - Application app(a_argc, a_argv); + Application app(argc, argv); result = app.exec(); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index fab6779307..99dd01174d 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -1541,7 +1541,11 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) { DocumentData *audio = audioId.audio; QString filepath = audio->filepath(DocumentData::FilePathResolveSaveFromData); if (!filepath.isEmpty()) { - psOpenFile(filepath); + if (documentIsValidMediaFile(filepath)) { + psOpenFile(filepath); + } else { + psShowInFolder(filepath); + } } } @@ -1568,7 +1572,11 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) { DocumentData *document = songId.song; QString filepath = document->filepath(DocumentData::FilePathResolveSaveFromData); if (!filepath.isEmpty()) { - psOpenFile(filepath); + if (documentIsValidMediaFile(filepath)) { + psOpenFile(filepath); + } else { + psShowInFolder(filepath); + } } } diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index cc0020b745..ba495270d2 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -505,9 +505,7 @@ void MainWindow::clearWidgets() { intro = 0; } if (_mediaView) { - if (!_mediaView->isHidden()) { - _mediaView->hide(); - } + hideMediaview(); _mediaView->rpcClear(); } title->updateBackButton(); diff --git a/Telegram/SourceFiles/platform/linux/file_dialog_linux.cpp b/Telegram/SourceFiles/platform/linux/file_dialog_linux.cpp new file mode 100644 index 0000000000..f47e871c6b --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/file_dialog_linux.cpp @@ -0,0 +1,497 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop 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 3 of the License, or +(at your option) any later version. + +It 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. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "platform/linux/file_dialog_linux.h" + +#include +#include "platform/linux/linux_libs.h" +#include "platform/linux/linux_gdk_helper.h" +#include "mainwindow.h" +#include "localstorage.h" + +QStringList qt_make_filter_list(const QString &filter); + +namespace Platform { +namespace FileDialog { + +using Type = ::FileDialog::internal::Type; + +bool Supported() { + return Platform::internal::GdkHelperLoaded() + && (Libs::gtk_widget_hide_on_delete != nullptr) + && (Libs::gtk_clipboard_store != nullptr) + && (Libs::gtk_clipboard_get != nullptr) + && (Libs::gtk_widget_destroy != nullptr) + && (Libs::gtk_dialog_get_type != nullptr) + && (Libs::gtk_dialog_run != nullptr) + && (Libs::gtk_widget_realize != nullptr) + && (Libs::gdk_window_set_modal_hint != nullptr) + && (Libs::gtk_widget_show != nullptr) + && (Libs::gdk_window_focus != nullptr) + && (Libs::gtk_widget_hide != nullptr) + && (Libs::gtk_widget_hide_on_delete != nullptr) + && (Libs::gtk_file_chooser_dialog_new != nullptr) + && (Libs::gtk_file_chooser_get_type != nullptr) + && (Libs::gtk_file_chooser_set_current_folder != nullptr) + && (Libs::gtk_file_chooser_get_current_folder != nullptr) + && (Libs::gtk_file_chooser_set_current_name != nullptr) + && (Libs::gtk_file_chooser_select_filename != nullptr) + && (Libs::gtk_file_chooser_get_filenames != nullptr) + && (Libs::gtk_file_chooser_set_filter != nullptr) + && (Libs::gtk_file_chooser_get_filter != nullptr) + && (Libs::gtk_window_get_type != nullptr) + && (Libs::gtk_window_set_title != nullptr) + && (Libs::gtk_file_chooser_set_local_only != nullptr) + && (Libs::gtk_file_chooser_set_action != nullptr) + && (Libs::gtk_file_chooser_set_select_multiple != nullptr) + && (Libs::gtk_file_chooser_set_do_overwrite_confirmation != nullptr) + && (Libs::gtk_file_chooser_remove_filter != nullptr) + && (Libs::gtk_file_filter_set_name != nullptr) + && (Libs::gtk_file_filter_add_pattern != nullptr) + && (Libs::gtk_file_chooser_add_filter != nullptr) + && (Libs::gtk_file_filter_new != nullptr); +} + +bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, Type type, QString startFile) { + auto parent = App::wnd() ? App::wnd()->filedialogParent() : nullptr; + internal::GtkFileDialog dialog(parent, caption, QString(), filter); + + dialog.setModal(true); + if (type == Type::ReadFile || type == Type::ReadFiles) { + dialog.setFileMode((type == Type::ReadFiles) ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile); + dialog.setAcceptMode(QFileDialog::AcceptOpen); + } else if (type == Type::ReadFolder) { + dialog.setAcceptMode(QFileDialog::AcceptOpen); + dialog.setFileMode(QFileDialog::Directory); + dialog.setOption(QFileDialog::ShowDirsOnly); + } else { + dialog.setFileMode(QFileDialog::AnyFile); + dialog.setAcceptMode(QFileDialog::AcceptSave); + } + if (startFile.isEmpty() || startFile.at(0) != '/') { + startFile = cDialogLastPath() + '/' + startFile; + } + dialog.selectFile(startFile); + + int res = dialog.exec(); + + QString path = dialog.directory().absolutePath(); + if (path != cDialogLastPath()) { + cSetDialogLastPath(path); + Local::writeUserSettings(); + } + + if (res == QDialog::Accepted) { + if (type == Type::ReadFiles) { + files = dialog.selectedFiles(); + } else { + files = dialog.selectedFiles().mid(0, 1); + } + return true; + } + + files = QStringList(); + remoteContent = QByteArray(); + return false; +} + +namespace internal { + +QGtkDialog::QGtkDialog(GtkWidget *gtkWidget) : gtkWidget(gtkWidget) { + Libs::g_signal_connect_swapped_helper(Libs::g_object_cast(gtkWidget), "response", GCallback(onResponse), this); + Libs::g_signal_connect_helper(Libs::g_object_cast(gtkWidget), "delete-event", GCallback(Libs::gtk_widget_hide_on_delete), NULL); +} + +QGtkDialog::~QGtkDialog() { + Libs::gtk_clipboard_store(Libs::gtk_clipboard_get(GDK_SELECTION_CLIPBOARD)); + Libs::gtk_widget_destroy(gtkWidget); +} + +GtkDialog *QGtkDialog::gtkDialog() const { + return Libs::gtk_dialog_cast(gtkWidget); +} + +void QGtkDialog::exec() { + if (auto w = App::wnd()) { + w->onReActivate(); + QTimer::singleShot(200, w, SLOT(onReActivate())); + } + if (modality() == Qt::ApplicationModal) { + // block input to the whole app, including other GTK dialogs + Libs::gtk_dialog_run(gtkDialog()); + } else { + // block input to the window, allow input to other GTK dialogs + QEventLoop loop; + connect(this, SIGNAL(accept()), &loop, SLOT(quit())); + connect(this, SIGNAL(reject()), &loop, SLOT(quit())); + loop.exec(); + } +} + +void QGtkDialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) { + connect(parent, &QWindow::destroyed, this, &QGtkDialog::onParentWindowDestroyed, + Qt::UniqueConnection); + setParent(parent); + setFlags(flags); + setModality(modality); + + Libs::gtk_widget_realize(gtkWidget); // creates X window + + if (parent) { + Platform::internal::XSetTransientForHint(Libs::gtk_widget_get_window(gtkWidget), parent->winId()); + } + + if (modality != Qt::NonModal) { + Libs::gdk_window_set_modal_hint(Libs::gtk_widget_get_window(gtkWidget), true); + QGuiApplicationPrivate::showModalWindow(this); + } + + Libs::gtk_widget_show(gtkWidget); + Libs::gdk_window_focus(Libs::gtk_widget_get_window(gtkWidget), 0); +} + +void QGtkDialog::hide() { + QGuiApplicationPrivate::hideModalWindow(this); + Libs::gtk_widget_hide(gtkWidget); +} + +void QGtkDialog::onResponse(QGtkDialog *dialog, int response) { + if (response == GTK_RESPONSE_OK) + emit dialog->accept(); + else + emit dialog->reject(); +} + +void QGtkDialog::onParentWindowDestroyed() { + // The Gtk*DialogHelper classes own this object. Make sure the parent doesn't delete it. + setParent(nullptr); +} + +namespace { + +const char *filterRegExp = +"^(.*)\\(([a-zA-Z0-9_.,*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$"; + +// Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)" +QStringList cleanFilterList(const QString &filter) { + QRegExp regexp(QString::fromLatin1(filterRegExp)); + Q_ASSERT(regexp.isValid()); + QString f = filter; + int i = regexp.indexIn(f); + if (i >= 0) + f = regexp.cap(2); + return f.split(QLatin1Char(' '), QString::SkipEmptyParts); +} + +} // namespace + +GtkFileDialog::GtkFileDialog(QWidget *parent, const QString &caption, const QString &directory, const QString &filter) : QDialog(parent) +, _windowTitle(caption) +, _initialDirectory(directory) { + auto filters = qt_make_filter_list(filter); + const int numFilters = filters.count(); + _nameFilters.reserve(numFilters); + for (int i = 0; i < numFilters; ++i) { + _nameFilters << filters[i].simplified(); + } + + d.reset(new QGtkDialog(Libs::gtk_file_chooser_dialog_new("", nullptr, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, NULL))); + connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted())); + connect(d.data(), SIGNAL(reject()), this, SLOT(onRejected())); + + Libs::g_signal_connect_helper(Libs::gtk_file_chooser_cast(d->gtkDialog()), "selection-changed", G_CALLBACK(onSelectionChanged), this); + Libs::g_signal_connect_swapped_helper(Libs::gtk_file_chooser_cast(d->gtkDialog()), "current-folder-changed", G_CALLBACK(onCurrentFolderChanged), this); +} + +GtkFileDialog::~GtkFileDialog() { +} + +void GtkFileDialog::showHelper(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) { + _dir.clear(); + _selection.clear(); + + applyOptions(); + return d->show(flags, modality, parent); +} + +void GtkFileDialog::setVisible(bool visible) { + if (visible) { + if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden)) { + return; + } + } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden)) { + return; + } + + if (visible) { + showHelper(windowFlags(), windowModality(), parentWidget() ? parentWidget()->windowHandle() : nullptr); + } else { + hideHelper(); + } + + // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below + // updates the state correctly, but skips showing the non-native version: + setAttribute(Qt::WA_DontShowOnScreen); + + QDialog::setVisible(visible); +} + +int GtkFileDialog::exec() { + d->setModality(windowModality()); + + bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose); + setAttribute(Qt::WA_DeleteOnClose, false); + + bool wasShowModal = testAttribute(Qt::WA_ShowModal); + setAttribute(Qt::WA_ShowModal, true); + setResult(0); + + show(); + + QPointer guard = this; + d->exec(); + if (guard.isNull()) + return QDialog::Rejected; + + setAttribute(Qt::WA_ShowModal, wasShowModal); + + return result(); +} + +void GtkFileDialog::hideHelper() { + // After GtkFileChooserDialog has been hidden, gtk_file_chooser_get_current_folder() + // & gtk_file_chooser_get_filenames() will return bogus values -> cache the actual + // values before hiding the dialog + _dir = directory().absolutePath(); + _selection = selectedFiles(); + + d->hide(); +} + +bool GtkFileDialog::defaultNameFilterDisables() const { + return false; +} + +void GtkFileDialog::setDirectory(const QString &directory) { + GtkDialog *gtkDialog = d->gtkDialog(); + Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), directory.toUtf8()); +} + +QDir GtkFileDialog::directory() const { + // While GtkFileChooserDialog is hidden, gtk_file_chooser_get_current_folder() + // returns a bogus value -> return the cached value before hiding + if (!_dir.isEmpty()) + return _dir; + + QString ret; + GtkDialog *gtkDialog = d->gtkDialog(); + gchar *folder = Libs::gtk_file_chooser_get_current_folder(Libs::gtk_file_chooser_cast(gtkDialog)); + if (folder) { + ret = QString::fromUtf8(folder); + Libs::g_free(folder); + } + return QDir(ret); +} + +void GtkFileDialog::selectFile(const QString &filename) { + _initialFiles.clear(); + _initialFiles.append(filename); +} + +QStringList GtkFileDialog::selectedFiles() const { + // While GtkFileChooserDialog is hidden, gtk_file_chooser_get_filenames() + // returns a bogus value -> return the cached value before hiding + if (!_selection.isEmpty()) + return _selection; + + QStringList selection; + GtkDialog *gtkDialog = d->gtkDialog(); + GSList *filenames = Libs::gtk_file_chooser_get_filenames(Libs::gtk_file_chooser_cast(gtkDialog)); + for (GSList *it = filenames; it; it = it->next) + selection += QString::fromUtf8((const char*)it->data); + Libs::g_slist_free(filenames); + return selection; +} + +void GtkFileDialog::setFilter() { + applyOptions(); +} + +void GtkFileDialog::selectNameFilter(const QString &filter) { + GtkFileFilter *gtkFilter = _filters.value(filter); + if (gtkFilter) { + GtkDialog *gtkDialog = d->gtkDialog(); + Libs::gtk_file_chooser_set_filter(Libs::gtk_file_chooser_cast(gtkDialog), gtkFilter); + } +} + +QString GtkFileDialog::selectedNameFilter() const { + GtkDialog *gtkDialog = d->gtkDialog(); + GtkFileFilter *gtkFilter = Libs::gtk_file_chooser_get_filter(Libs::gtk_file_chooser_cast(gtkDialog)); + return _filterNames.value(gtkFilter); +} + +void GtkFileDialog::onAccepted() { + emit accept(); + +// QString filter = selectedNameFilter(); +// if (filter.isEmpty()) +// emit filterSelected(filter); + +// QList files = selectedFiles(); +// emit filesSelected(files); +// if (files.count() == 1) +// emit fileSelected(files.first()); +} + +void GtkFileDialog::onRejected() { + emit reject(); + +// +} + +void GtkFileDialog::onSelectionChanged(GtkDialog *gtkDialog, GtkFileDialog *helper) { +// QString selection; +// gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(gtkDialog)); +// if (filename) { +// selection = QString::fromUtf8(filename); +// g_free(filename); +// } +// emit helper->currentChanged(QUrl::fromLocalFile(selection)); +} + +void GtkFileDialog::onCurrentFolderChanged(GtkFileDialog *dialog) { +// emit dialog->directoryEntered(dialog->directory()); +} + +GtkFileChooserAction gtkFileChooserAction(QFileDialog::FileMode fileMode, QFileDialog::AcceptMode acceptMode) { + switch (fileMode) { + case QFileDialog::AnyFile: + case QFileDialog::ExistingFile: + case QFileDialog::ExistingFiles: + if (acceptMode == QFileDialog::AcceptOpen) + return GTK_FILE_CHOOSER_ACTION_OPEN; + else + return GTK_FILE_CHOOSER_ACTION_SAVE; + case QFileDialog::Directory: + case QFileDialog::DirectoryOnly: + default: + if (acceptMode == QFileDialog::AcceptOpen) + return GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; + else + return GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER; + } +} + +bool CustomButtonsSupported() { + return (Libs::gtk_dialog_get_widget_for_response != nullptr) + && (Libs::gtk_button_set_label != nullptr) + && (Libs::gtk_button_get_type != nullptr); +} + +void GtkFileDialog::applyOptions() { + GtkDialog *gtkDialog = d->gtkDialog(); + + Libs::gtk_window_set_title(Libs::gtk_window_cast(gtkDialog), _windowTitle.toUtf8()); + Libs::gtk_file_chooser_set_local_only(Libs::gtk_file_chooser_cast(gtkDialog), true); + + const GtkFileChooserAction action = gtkFileChooserAction(_fileMode, _acceptMode); + Libs::gtk_file_chooser_set_action(Libs::gtk_file_chooser_cast(gtkDialog), action); + + const bool selectMultiple = (_fileMode == QFileDialog::ExistingFiles); + Libs::gtk_file_chooser_set_select_multiple(Libs::gtk_file_chooser_cast(gtkDialog), selectMultiple); + + const bool confirmOverwrite = !_options.testFlag(QFileDialog::DontConfirmOverwrite); + Libs::gtk_file_chooser_set_do_overwrite_confirmation(Libs::gtk_file_chooser_cast(gtkDialog), confirmOverwrite); + + if (!_nameFilters.isEmpty()) + setNameFilters(_nameFilters); + + if (!_initialDirectory.isEmpty()) + setDirectory(_initialDirectory); + + for_const (const auto &filename, _initialFiles) { + if (_acceptMode == QFileDialog::AcceptSave) { + QFileInfo fi(filename); + Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), fi.path().toUtf8()); + Libs::gtk_file_chooser_set_current_name(Libs::gtk_file_chooser_cast(gtkDialog), fi.fileName().toUtf8()); + } else if (filename.endsWith('/')) { + Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), filename.toUtf8()); + } else { + Libs::gtk_file_chooser_select_filename(Libs::gtk_file_chooser_cast(gtkDialog), filename.toUtf8()); + } + } + + const QString initialNameFilter = _nameFilters.isEmpty() ? QString() : _nameFilters.front(); + if (!initialNameFilter.isEmpty()) + selectNameFilter(initialNameFilter); + + if (CustomButtonsSupported()) { + GtkWidget *acceptButton = Libs::gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_OK); + if (acceptButton) { + /*if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept)) + Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), opts->labelText(QFileDialogOptions::Accept).toUtf8()); + else*/ if (_acceptMode == QFileDialog::AcceptOpen) + Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), GTK_STOCK_OPEN); + else + Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), GTK_STOCK_SAVE); + } + + GtkWidget *rejectButton = Libs::gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_CANCEL); + if (rejectButton) { + /*if (opts->isLabelExplicitlySet(QFileDialogOptions::Reject)) + Libs::gtk_button_set_label(Libs::gtk_button_cast(rejectButton), opts->labelText(QFileDialogOptions::Reject).toUtf8()); + else*/ + Libs::gtk_button_set_label(Libs::gtk_button_cast(rejectButton), GTK_STOCK_CANCEL); + } + } +} + +void GtkFileDialog::setNameFilters(const QStringList &filters) { + GtkDialog *gtkDialog = d->gtkDialog(); + foreach (GtkFileFilter *filter, _filters) + Libs::gtk_file_chooser_remove_filter(Libs::gtk_file_chooser_cast(gtkDialog), filter); + + _filters.clear(); + _filterNames.clear(); + + foreach (const QString &filter, filters) { + GtkFileFilter *gtkFilter = Libs::gtk_file_filter_new(); + const QString name = filter.left(filter.indexOf(QLatin1Char('('))); + const QStringList extensions = cleanFilterList(filter); + + Libs::gtk_file_filter_set_name(gtkFilter, name.isEmpty() ? extensions.join(QStringLiteral(", ")).toUtf8() : name.toUtf8()); + foreach (const QString &ext, extensions) + Libs::gtk_file_filter_add_pattern(gtkFilter, ext.toUtf8()); + + Libs::gtk_file_chooser_add_filter(Libs::gtk_file_chooser_cast(gtkDialog), gtkFilter); + + _filters.insert(filter, gtkFilter); + _filterNames.insert(gtkFilter, filter); + } +} + +} // namespace internal +} // namespace FileDialog +} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/file_dialog_linux.h b/Telegram/SourceFiles/platform/linux/file_dialog_linux.h new file mode 100644 index 0000000000..3cc2a935de --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/file_dialog_linux.h @@ -0,0 +1,145 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop 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 3 of the License, or +(at your option) any later version. + +It 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. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "ui/filedialog.h" + +extern "C" { +#undef signals +#include +#include +#define signals public +} // extern "C" + +namespace Platform { +namespace FileDialog { + +bool Supported(); + +bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile); + +namespace internal { + +// This is a patched copy of qgtk2 theme plugin. +// We need to use our own gtk file dialog instead of +// styling Qt file dialog, because Qt only works with gtk2. +// We need to be able to work with gtk2 and gtk3, because +// we use gtk3 to work with appindicator3. +class QGtkDialog : public QWindow { + Q_OBJECT + +public: + QGtkDialog(GtkWidget *gtkWidget); + ~QGtkDialog(); + + GtkDialog *gtkDialog() const; + + void exec(); + void show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent); + void hide(); + +signals: + void accept(); + void reject(); + +protected: + static void onResponse(QGtkDialog *dialog, int response); + +private slots: + void onParentWindowDestroyed(); + +private: + GtkWidget *gtkWidget; + +}; + +class GtkFileDialog : public QDialog { + Q_OBJECT + +public: + GtkFileDialog(QWidget *parent = Q_NULLPTR, + const QString &caption = QString(), + const QString &directory = QString(), + const QString &filter = QString()); + ~GtkFileDialog(); + + void setVisible(bool visible) override; + + void setWindowTitle(const QString &windowTitle) { + _windowTitle = windowTitle; + } + void setAcceptMode(QFileDialog::AcceptMode acceptMode) { + _acceptMode = acceptMode; + } + void setFileMode(QFileDialog::FileMode fileMode) { + _fileMode = fileMode; + } + void setOption(QFileDialog::Option option, bool on = true) { + if (on) { + _options |= option; + } else { + _options &= ~option; + } + } + + int exec() override; + + bool defaultNameFilterDisables() const; + void setDirectory(const QString &directory); + QDir directory() const; + void selectFile(const QString &filename); + QStringList selectedFiles() const; + void setFilter(); + void selectNameFilter(const QString &filter); + QString selectedNameFilter() const; + +private slots: + void onAccepted(); + void onRejected(); + +private: + static void onSelectionChanged(GtkDialog *dialog, GtkFileDialog *helper); + static void onCurrentFolderChanged(GtkFileDialog *helper); + void applyOptions(); + void setNameFilters(const QStringList &filters); + + void showHelper(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent); + void hideHelper(); + + // Options + QFileDialog::Options _options = { 0 }; + QString _windowTitle = "Choose file"; + QString _initialDirectory; + QStringList _initialFiles; + QStringList _nameFilters; + QFileDialog::AcceptMode _acceptMode = QFileDialog::AcceptOpen; + QFileDialog::FileMode _fileMode = QFileDialog::ExistingFile; + + QString _dir; + QStringList _selection; + QHash _filters; + QHash _filterNames; + QScopedPointer d; +}; + +} // namespace internal +} // namespace FileDialog +} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp new file mode 100644 index 0000000000..17e93b8603 --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp @@ -0,0 +1,114 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop 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 3 of the License, or +(at your option) any later version. + +It 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. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "platform/linux/linux_gdk_helper.h" + +#include "platform/linux/linux_libs.h" + +extern "C" { +#undef signals +#include +#define signals public +} // extern "C" + +namespace Platform { +namespace internal { + +enum class GtkLoaded { + GtkNone, + Gtk2, + Gtk3, +}; + +GtkLoaded gdk_helper_loaded = GtkLoaded::GtkNone; + +// To be able to compile with gtk-3.0 headers as well +#define GdkDrawable GdkWindow + +// Gtk 2 +using f_gdk_x11_drawable_get_xdisplay = Display*(*)(GdkDrawable*); +f_gdk_x11_drawable_get_xdisplay gdk_x11_drawable_get_xdisplay = nullptr; + +using f_gdk_x11_drawable_get_xid = XID(*)(GdkDrawable*); +f_gdk_x11_drawable_get_xid gdk_x11_drawable_get_xid = nullptr; + +// Gtk 3 +using f_gdk_x11_window_get_type = GType (*)(void); +f_gdk_x11_window_get_type gdk_x11_window_get_type = nullptr; + +// To be able to compile with gtk-2.0 headers as well +template +inline bool gdk_is_x11_window_check(Object *obj) { + return Libs::g_type_cit_helper(obj, gdk_x11_window_get_type()); +} + +using f_gdk_window_get_display = GdkDisplay*(*)(GdkWindow *window); +f_gdk_window_get_display gdk_window_get_display = nullptr; + +using f_gdk_x11_display_get_xdisplay = Display*(*)(GdkDisplay *display); +f_gdk_x11_display_get_xdisplay gdk_x11_display_get_xdisplay = nullptr; + +using f_gdk_x11_window_get_xid = Window(*)(GdkWindow *window); +f_gdk_x11_window_get_xid gdk_x11_window_get_xid = nullptr; + +bool GdkHelperLoadGtk2(QLibrary &lib) { + if (!Libs::load(lib, "gdk_x11_drawable_get_xdisplay", gdk_x11_drawable_get_xdisplay)) return false; + if (!Libs::load(lib, "gdk_x11_drawable_get_xid", gdk_x11_drawable_get_xid)) return false; + return true; +} + +bool GdkHelperLoadGtk3(QLibrary &lib) { + if (!Libs::load(lib, "gdk_x11_window_get_type", gdk_x11_window_get_type)) return false; + if (!Libs::load(lib, "gdk_window_get_display", gdk_window_get_display)) return false; + if (!Libs::load(lib, "gdk_x11_display_get_xdisplay", gdk_x11_display_get_xdisplay)) return false; + if (!Libs::load(lib, "gdk_x11_window_get_xid", gdk_x11_window_get_xid)) return false; + return true; +} + +void GdkHelperLoad(QLibrary &lib) { + gdk_helper_loaded = GtkLoaded::GtkNone; + if (GdkHelperLoadGtk2(lib)) { + gdk_helper_loaded = GtkLoaded::Gtk2; + } else if (GdkHelperLoadGtk3(lib)) { + gdk_helper_loaded = GtkLoaded::Gtk3; + } +} + +bool GdkHelperLoaded() { + return gdk_helper_loaded != GtkLoaded::GtkNone; +} + +void XSetTransientForHint(GdkWindow *window, quintptr winId) { + if (gdk_helper_loaded == GtkLoaded::Gtk2) { + ::XSetTransientForHint(gdk_x11_drawable_get_xdisplay(window), + gdk_x11_drawable_get_xid(window), + winId); + } else if (gdk_helper_loaded == GtkLoaded::Gtk3) { + if (gdk_is_x11_window_check(window)) { + ::XSetTransientForHint(gdk_x11_display_get_xdisplay(gdk_window_get_display(window)), + gdk_x11_window_get_xid(window), + winId); + } + } +} + +} // namespace internal +} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h new file mode 100644 index 0000000000..dd049480b6 --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h @@ -0,0 +1,40 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop 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 3 of the License, or +(at your option) any later version. + +It 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. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include + +extern "C" { +#undef signals +#include +#include +#define signals public +} // extern "C" + +namespace Platform { +namespace internal { + +void GdkHelperLoad(QLibrary &lib); +bool GdkHelperLoaded(); +void XSetTransientForHint(GdkWindow *window, quintptr winId); + +} // namespace internal +} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_libs.cpp b/Telegram/SourceFiles/platform/linux/linux_libs.cpp index 63bbf96c88..484b6c534d 100644 --- a/Telegram/SourceFiles/platform/linux/linux_libs.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_libs.cpp @@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "stdafx.h" #include "platform/linux/linux_libs.h" +#include "platform/linux/linux_gdk_helper.h" + namespace Platform { namespace Libs { namespace { @@ -42,27 +44,62 @@ bool loadLibrary(QLibrary &lib, const char *name, int version) { } bool setupGtkBase(QLibrary &lib_gtk) { - if (!load(lib_gtk, "gtk_init_check", gtk_init_check)) return false; - if (!load(lib_gtk, "gtk_menu_new", gtk_menu_new)) return false; - if (!load(lib_gtk, "gtk_menu_get_type", gtk_menu_get_type)) return false; + if (!load(lib_gtk, "gtk_init_check", gtk_init_check)) return false; + if (!load(lib_gtk, "gtk_menu_new", gtk_menu_new)) return false; + if (!load(lib_gtk, "gtk_menu_get_type", gtk_menu_get_type)) return false; - if (!load(lib_gtk, "gtk_menu_item_new_with_label", gtk_menu_item_new_with_label)) return false; - if (!load(lib_gtk, "gtk_menu_item_set_label", gtk_menu_item_set_label)) return false; - if (!load(lib_gtk, "gtk_menu_shell_append", gtk_menu_shell_append)) return false; - if (!load(lib_gtk, "gtk_menu_shell_get_type", gtk_menu_shell_get_type)) return false; - if (!load(lib_gtk, "gtk_widget_show", gtk_widget_show)) return false; - if (!load(lib_gtk, "gtk_widget_get_toplevel", gtk_widget_get_toplevel)) return false; - if (!load(lib_gtk, "gtk_widget_get_visible", gtk_widget_get_visible)) return false; - if (!load(lib_gtk, "gtk_widget_set_sensitive", gtk_widget_set_sensitive)) return false; + if (!load(lib_gtk, "gtk_menu_item_new_with_label", gtk_menu_item_new_with_label)) return false; + if (!load(lib_gtk, "gtk_menu_item_set_label", gtk_menu_item_set_label)) return false; + if (!load(lib_gtk, "gtk_menu_shell_append", gtk_menu_shell_append)) return false; + if (!load(lib_gtk, "gtk_menu_shell_get_type", gtk_menu_shell_get_type)) return false; + if (!load(lib_gtk, "gtk_widget_show", gtk_widget_show)) return false; + if (!load(lib_gtk, "gtk_widget_hide", gtk_widget_hide)) return false; + if (!load(lib_gtk, "gtk_widget_get_toplevel", gtk_widget_get_toplevel)) return false; + if (!load(lib_gtk, "gtk_widget_get_visible", gtk_widget_get_visible)) return false; + if (!load(lib_gtk, "gtk_widget_get_window", gtk_widget_get_window)) return false; + if (!load(lib_gtk, "gtk_widget_set_sensitive", gtk_widget_set_sensitive)) return false; + if (!load(lib_gtk, "gtk_widget_realize", gtk_widget_realize)) return false; + if (!load(lib_gtk, "gtk_widget_hide_on_delete", gtk_widget_hide_on_delete)) return false; + if (!load(lib_gtk, "gtk_widget_destroy", gtk_widget_destroy)) return false; + if (!load(lib_gtk, "gtk_clipboard_get", gtk_clipboard_get)) return false; + if (!load(lib_gtk, "gtk_clipboard_store", gtk_clipboard_store)) return false; + if (!load(lib_gtk, "gtk_file_chooser_dialog_new", gtk_file_chooser_dialog_new)) return false; + if (!load(lib_gtk, "gtk_file_chooser_get_type", gtk_file_chooser_get_type)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_current_folder", gtk_file_chooser_set_current_folder)) return false; + if (!load(lib_gtk, "gtk_file_chooser_get_current_folder", gtk_file_chooser_get_current_folder)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_current_name", gtk_file_chooser_set_current_name)) return false; + if (!load(lib_gtk, "gtk_file_chooser_select_filename", gtk_file_chooser_select_filename)) return false; + if (!load(lib_gtk, "gtk_file_chooser_get_filenames", gtk_file_chooser_get_filenames)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_filter", gtk_file_chooser_set_filter)) return false; + if (!load(lib_gtk, "gtk_file_chooser_get_filter", gtk_file_chooser_get_filter)) return false; + if (!load(lib_gtk, "gtk_window_get_type", gtk_window_get_type)) return false; + if (!load(lib_gtk, "gtk_window_set_title", gtk_window_set_title)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_local_only", gtk_file_chooser_set_local_only)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_action", gtk_file_chooser_set_action)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_select_multiple", gtk_file_chooser_set_select_multiple)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_do_overwrite_confirmation", gtk_file_chooser_set_do_overwrite_confirmation)) return false; + if (!load(lib_gtk, "gtk_file_chooser_remove_filter", gtk_file_chooser_remove_filter)) return false; + if (!load(lib_gtk, "gtk_file_filter_set_name", gtk_file_filter_set_name)) return false; + if (!load(lib_gtk, "gtk_file_filter_add_pattern", gtk_file_filter_add_pattern)) return false; + if (!load(lib_gtk, "gtk_file_chooser_add_filter", gtk_file_chooser_add_filter)) return false; + if (!load(lib_gtk, "gtk_file_filter_new", gtk_file_filter_new)) return false; - if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false; - if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false; + if (!load(lib_gtk, "gdk_window_set_modal_hint", gdk_window_set_modal_hint)) return false; + if (!load(lib_gtk, "gdk_window_focus", gdk_window_focus)) return false; + if (!load(lib_gtk, "gtk_dialog_get_type", gtk_dialog_get_type)) return false; + if (!load(lib_gtk, "gtk_dialog_run", gtk_dialog_run)) return false; - if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false; - if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false; + if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false; + if (!load(lib_gtk, "g_type_check_instance_is_a", g_type_check_instance_is_a)) return false; + if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false; - DEBUG_LOG(("Library gtk functions loaded!")); - if (!gtk_init_check(0, 0)) { + if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false; + if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false; + if (!load(lib_gtk, "g_free", g_free)) return false; + if (!load(lib_gtk, "g_slist_free", g_slist_free)) return false; + + DEBUG_LOG(("Library gtk functions loaded!")); + if (!gtk_init_check(0, 0)) { gtk_init_check = nullptr; DEBUG_LOG(("Failed to gtk_init_check(0, 0)!")); return false; @@ -73,12 +110,12 @@ bool setupGtkBase(QLibrary &lib_gtk) { } bool setupAppIndicator(QLibrary &lib_indicator) { - if (!load(lib_indicator, "app_indicator_new", app_indicator_new)) return false; - if (!load(lib_indicator, "app_indicator_set_status", app_indicator_set_status)) return false; - if (!load(lib_indicator, "app_indicator_set_menu", app_indicator_set_menu)) return false; - if (!load(lib_indicator, "app_indicator_set_icon_full", app_indicator_set_icon_full)) return false; + if (!load(lib_indicator, "app_indicator_new", app_indicator_new)) return false; + if (!load(lib_indicator, "app_indicator_set_status", app_indicator_set_status)) return false; + if (!load(lib_indicator, "app_indicator_set_menu", app_indicator_set_menu)) return false; + if (!load(lib_indicator, "app_indicator_set_icon_full", app_indicator_set_icon_full)) return false; - DEBUG_LOG(("Library appindicator functions loaded!")); + DEBUG_LOG(("Library appindicator functions loaded!")); return true; } @@ -92,10 +129,45 @@ f_gtk_menu_item_set_label gtk_menu_item_set_label = nullptr; f_gtk_menu_shell_append gtk_menu_shell_append = nullptr; f_gtk_menu_shell_get_type gtk_menu_shell_get_type = nullptr; f_gtk_widget_show gtk_widget_show = nullptr; +f_gtk_widget_hide gtk_widget_hide = nullptr; f_gtk_widget_get_toplevel gtk_widget_get_toplevel = nullptr; f_gtk_widget_get_visible gtk_widget_get_visible = nullptr; +f_gtk_widget_get_window gtk_widget_get_window = nullptr; f_gtk_widget_set_sensitive gtk_widget_set_sensitive = nullptr; +f_gtk_widget_realize gtk_widget_realize = nullptr; +f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete = nullptr; +f_gtk_widget_destroy gtk_widget_destroy = nullptr; +f_gtk_clipboard_get gtk_clipboard_get = nullptr; +f_gtk_clipboard_store gtk_clipboard_store = nullptr; +f_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new = nullptr; +f_gtk_file_chooser_get_type gtk_file_chooser_get_type = nullptr; +f_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder = nullptr; +f_gtk_file_chooser_get_current_folder gtk_file_chooser_get_current_folder = nullptr; +f_gtk_file_chooser_set_current_name gtk_file_chooser_set_current_name = nullptr; +f_gtk_file_chooser_select_filename gtk_file_chooser_select_filename = nullptr; +f_gtk_file_chooser_get_filenames gtk_file_chooser_get_filenames = nullptr; +f_gtk_file_chooser_set_filter gtk_file_chooser_set_filter = nullptr; +f_gtk_file_chooser_get_filter gtk_file_chooser_get_filter = nullptr; +f_gtk_window_get_type gtk_window_get_type = nullptr; +f_gtk_window_set_title gtk_window_set_title = nullptr; +f_gtk_file_chooser_set_local_only gtk_file_chooser_set_local_only = nullptr; +f_gtk_file_chooser_set_action gtk_file_chooser_set_action = nullptr; +f_gtk_file_chooser_set_select_multiple gtk_file_chooser_set_select_multiple = nullptr; +f_gtk_file_chooser_set_do_overwrite_confirmation gtk_file_chooser_set_do_overwrite_confirmation = nullptr; +f_gtk_file_chooser_remove_filter gtk_file_chooser_remove_filter = nullptr; +f_gtk_file_filter_set_name gtk_file_filter_set_name = nullptr; +f_gtk_file_filter_add_pattern gtk_file_filter_add_pattern = nullptr; +f_gtk_file_chooser_add_filter gtk_file_chooser_add_filter = nullptr; +f_gtk_file_filter_new gtk_file_filter_new = nullptr; +f_gtk_dialog_get_widget_for_response gtk_dialog_get_widget_for_response = nullptr; +f_gtk_button_set_label gtk_button_set_label = nullptr; +f_gtk_button_get_type gtk_button_get_type = nullptr; +f_gdk_window_set_modal_hint gdk_window_set_modal_hint = nullptr; +f_gdk_window_focus gdk_window_focus = nullptr; +f_gtk_dialog_get_type gtk_dialog_get_type = nullptr; +f_gtk_dialog_run gtk_dialog_run = nullptr; f_g_type_check_instance_cast g_type_check_instance_cast = nullptr; +f_g_type_check_instance_is_a g_type_check_instance_is_a = nullptr; f_g_signal_connect_data g_signal_connect_data = nullptr; f_app_indicator_new app_indicator_new = nullptr; f_app_indicator_set_status app_indicator_set_status = nullptr; @@ -118,9 +190,13 @@ f_gtk_get_current_event_time gtk_get_current_event_time = nullptr; f_g_object_ref_sink g_object_ref_sink = nullptr; f_g_object_unref g_object_unref = nullptr; f_g_idle_add g_idle_add = nullptr; +f_g_free g_free = nullptr; +f_g_slist_free g_slist_free = nullptr; +#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION f_unity_launcher_entry_set_count unity_launcher_entry_set_count = nullptr; f_unity_launcher_entry_set_count_visible unity_launcher_entry_set_count_visible = nullptr; f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id = nullptr; +#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION void start() { DEBUG_LOG(("Loading libraries")); @@ -170,10 +246,17 @@ void start() { load(lib_gtk, "gtk_menu_popup", gtk_menu_popup); load(lib_gtk, "gtk_get_current_event_time", gtk_get_current_event_time); load(lib_gtk, "g_idle_add", g_idle_add); + + internal::GdkHelperLoad(lib_gtk); + + load(lib_gtk, "gtk_dialog_get_widget_for_response", gtk_dialog_get_widget_for_response); + load(lib_gtk, "gtk_button_set_label", gtk_button_set_label); + load(lib_gtk, "gtk_button_get_type", gtk_button_get_type); } else { LOG(("Could not load gtk-x11-2.0!")); } +#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION if (QString(getenv("XDG_CURRENT_DESKTOP")).toLower() == qstr("unity")) { QLibrary lib_unity(qstr("unity"), 9, 0); loadLibrary(lib_unity, "unity", 9); @@ -182,6 +265,7 @@ void start() { load(lib_unity, "unity_launcher_entry_set_count", unity_launcher_entry_set_count); load(lib_unity, "unity_launcher_entry_set_count_visible", unity_launcher_entry_set_count_visible); } +#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION } } // namespace Libs diff --git a/Telegram/SourceFiles/platform/linux/linux_libs.h b/Telegram/SourceFiles/platform/linux/linux_libs.h index 459d666bb7..d51db1c677 100644 --- a/Telegram/SourceFiles/platform/linux/linux_libs.h +++ b/Telegram/SourceFiles/platform/linux/linux_libs.h @@ -24,10 +24,13 @@ extern "C" { #undef signals #include #include +#include #define signals public } // extern "C" +#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION #include +#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION namespace Platform { namespace Libs { @@ -73,15 +76,102 @@ extern f_gtk_menu_shell_get_type gtk_menu_shell_get_type; typedef void (*f_gtk_widget_show)(GtkWidget *widget); extern f_gtk_widget_show gtk_widget_show; +typedef void (*f_gtk_widget_hide)(GtkWidget *widget); +extern f_gtk_widget_hide gtk_widget_hide; + typedef GtkWidget* (*f_gtk_widget_get_toplevel)(GtkWidget *widget); extern f_gtk_widget_get_toplevel gtk_widget_get_toplevel; typedef gboolean (*f_gtk_widget_get_visible)(GtkWidget *widget); extern f_gtk_widget_get_visible gtk_widget_get_visible; +typedef GdkWindow* (*f_gtk_widget_get_window)(GtkWidget *widget); +extern f_gtk_widget_get_window gtk_widget_get_window; + typedef void (*f_gtk_widget_set_sensitive)(GtkWidget *widget, gboolean sensitive); extern f_gtk_widget_set_sensitive gtk_widget_set_sensitive; +typedef void (*f_gtk_widget_realize)(GtkWidget *widget); +extern f_gtk_widget_realize gtk_widget_realize; + +typedef gboolean (*f_gtk_widget_hide_on_delete)(GtkWidget *widget); +extern f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete; + +typedef void (*f_gtk_widget_destroy)(GtkWidget *widget); +extern f_gtk_widget_destroy gtk_widget_destroy; + +typedef GtkClipboard* (*f_gtk_clipboard_get)(GdkAtom selection); +extern f_gtk_clipboard_get gtk_clipboard_get; + +typedef void (*f_gtk_clipboard_store)(GtkClipboard *clipboard); +extern f_gtk_clipboard_store gtk_clipboard_store; + +typedef GtkWidget* (*f_gtk_file_chooser_dialog_new)(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...) G_GNUC_NULL_TERMINATED; +extern f_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new; + +typedef gboolean (*f_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, const gchar *filename); +extern f_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder; + +typedef gchar *(*f_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser); +extern f_gtk_file_chooser_get_current_folder gtk_file_chooser_get_current_folder; + +typedef void (*f_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, const gchar *name); +extern f_gtk_file_chooser_set_current_name gtk_file_chooser_set_current_name; + +typedef gboolean (*f_gtk_file_chooser_select_filename)(GtkFileChooser *chooser, const char *filename); +extern f_gtk_file_chooser_select_filename gtk_file_chooser_select_filename; + +typedef GSList* (*f_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); +extern f_gtk_file_chooser_get_filenames gtk_file_chooser_get_filenames; + +typedef void (*f_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); +extern f_gtk_file_chooser_set_filter gtk_file_chooser_set_filter; + +typedef GtkFileFilter* (*f_gtk_file_chooser_get_filter)(GtkFileChooser *chooser); +extern f_gtk_file_chooser_get_filter gtk_file_chooser_get_filter; + +typedef void (*f_gtk_window_set_title)(GtkWindow *window, const gchar *title); +extern f_gtk_window_set_title gtk_window_set_title; + +typedef void (*f_gtk_file_chooser_set_local_only)(GtkFileChooser *chooser, gboolean local_only); +extern f_gtk_file_chooser_set_local_only gtk_file_chooser_set_local_only; + +typedef void (*f_gtk_file_chooser_set_action)(GtkFileChooser *chooser, GtkFileChooserAction action); +extern f_gtk_file_chooser_set_action gtk_file_chooser_set_action; + +typedef void (*f_gtk_file_chooser_set_select_multiple)(GtkFileChooser *chooser, gboolean select_multiple); +extern f_gtk_file_chooser_set_select_multiple gtk_file_chooser_set_select_multiple; + +typedef void (*f_gtk_file_chooser_set_do_overwrite_confirmation)(GtkFileChooser *chooser, gboolean do_overwrite_confirmation); +extern f_gtk_file_chooser_set_do_overwrite_confirmation gtk_file_chooser_set_do_overwrite_confirmation; + +typedef GtkWidget* (*f_gtk_dialog_get_widget_for_response)(GtkDialog *dialog, gint response_id); +extern f_gtk_dialog_get_widget_for_response gtk_dialog_get_widget_for_response; + +typedef void (*f_gtk_button_set_label)(GtkButton *button, const gchar *label); +extern f_gtk_button_set_label gtk_button_set_label; + +typedef void (*f_gtk_file_chooser_remove_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); +extern f_gtk_file_chooser_remove_filter gtk_file_chooser_remove_filter; + +typedef void (*f_gtk_file_filter_set_name)(GtkFileFilter *filter, const gchar *name); +extern f_gtk_file_filter_set_name gtk_file_filter_set_name; + +typedef void (*f_gtk_file_filter_add_pattern)(GtkFileFilter *filter, const gchar *pattern); +extern f_gtk_file_filter_add_pattern gtk_file_filter_add_pattern; + +typedef void (*f_gtk_file_chooser_add_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); +extern f_gtk_file_chooser_add_filter gtk_file_chooser_add_filter; + +typedef GtkFileFilter* (*f_gtk_file_filter_new)(void); +extern f_gtk_file_filter_new gtk_file_filter_new; + +typedef void (*f_gdk_window_set_modal_hint)(GdkWindow *window, gboolean modal); +extern f_gdk_window_set_modal_hint gdk_window_set_modal_hint; + +typedef void (*f_gdk_window_focus)(GdkWindow *window, guint32 timestamp); +extern f_gdk_window_focus gdk_window_focus; + typedef GTypeInstance* (*f_g_type_check_instance_cast)(GTypeInstance *instance, GType iface_type); extern f_g_type_check_instance_cast g_type_check_instance_cast; @@ -89,21 +179,82 @@ template inline Result *g_type_cic_helper(Object *instance, GType iface_type) { return reinterpret_cast(g_type_check_instance_cast(reinterpret_cast(instance), iface_type)); } + template inline GtkMenu *gtk_menu_cast(Object *obj) { return g_type_cic_helper(obj, gtk_menu_get_type()); } + template inline GtkMenuShell *gtk_menu_shell_cast(Object *obj) { return g_type_cic_helper(obj, gtk_menu_get_type()); } +typedef GType (*f_gtk_dialog_get_type)(void) G_GNUC_CONST; +extern f_gtk_dialog_get_type gtk_dialog_get_type; + +template +inline GtkDialog *gtk_dialog_cast(Object *obj) { + return g_type_cic_helper(obj, gtk_dialog_get_type()); +} + +template +inline GObject *g_object_cast(Object *obj) { + return g_type_cic_helper(obj, G_TYPE_OBJECT); +} + +typedef GType (*f_gtk_file_chooser_get_type)(void) G_GNUC_CONST; +extern f_gtk_file_chooser_get_type gtk_file_chooser_get_type; + +template +inline GtkFileChooser *gtk_file_chooser_cast(Object *obj) { + return g_type_cic_helper(obj, gtk_file_chooser_get_type()); +} + +typedef GType (*f_gtk_button_get_type)(void) G_GNUC_CONST; +extern f_gtk_button_get_type gtk_button_get_type; + +template +inline GtkButton *gtk_button_cast(Object *obj) { + return g_type_cic_helper(obj, gtk_button_get_type()); +} + +typedef GType (*f_gtk_window_get_type)(void) G_GNUC_CONST; +extern f_gtk_window_get_type gtk_window_get_type; + +template +inline GtkWindow *gtk_window_cast(Object *obj) { + return g_type_cic_helper(obj, gtk_window_get_type()); +} + +typedef gboolean (*f_g_type_check_instance_is_a)(GTypeInstance *instance, GType iface_type) G_GNUC_PURE; +extern f_g_type_check_instance_is_a g_type_check_instance_is_a; + +template +inline bool g_type_cit_helper(Object *instance, GType iface_type) { + if (!instance) return false; + + auto ginstance = reinterpret_cast(instance); + if (ginstance->g_class && ginstance->g_class->g_type == iface_type) { + return true; + } + return g_type_check_instance_is_a(ginstance, iface_type); +} + +typedef gint (*f_gtk_dialog_run)(GtkDialog *dialog); +extern f_gtk_dialog_run gtk_dialog_run; + typedef gulong (*f_g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags); extern f_g_signal_connect_data g_signal_connect_data; + inline gulong g_signal_connect_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data) { return g_signal_connect_data(instance, detailed_signal, c_handler, data, NULL, (GConnectFlags)0); } +inline gulong g_signal_connect_swapped_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data) { + return g_signal_connect_data(instance, detailed_signal, c_handler, data, NULL, G_CONNECT_SWAPPED); +} + typedef AppIndicator* (*f_app_indicator_new)(const gchar *id, const gchar *icon_name, AppIndicatorCategory category); extern f_app_indicator_new app_indicator_new; @@ -167,6 +318,13 @@ extern f_g_object_unref g_object_unref; typedef guint (*f_g_idle_add)(GSourceFunc function, gpointer data); extern f_g_idle_add g_idle_add; +typedef void (*f_g_free)(gpointer mem); +extern f_g_free g_free; + +typedef void (*f_g_slist_free)(GSList *list); +extern f_g_slist_free g_slist_free; + +#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION typedef void (*f_unity_launcher_entry_set_count)(UnityLauncherEntry* self, gint64 value); extern f_unity_launcher_entry_set_count unity_launcher_entry_set_count; @@ -175,6 +333,7 @@ extern f_unity_launcher_entry_set_count_visible unity_launcher_entry_set_count_v typedef UnityLauncherEntry* (*f_unity_launcher_entry_get_for_desktop_id)(const gchar* desktop_id); extern f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id; +#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION } // namespace Libs } // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index dfc4b74626..8971a4976f 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -181,7 +181,9 @@ static gboolean _trayIconCheck(gpointer/* pIn*/) { return FALSE; } +#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION UnityLauncherEntry *_psUnityLauncherEntry = nullptr; +#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION } // namespace @@ -319,6 +321,7 @@ void MainWindow::psUpdateCounter() { int32 counter = App::histories().unreadBadge(); setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram")); +#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION if (_psUnityLauncherEntry) { if (counter > 0) { Libs::unity_launcher_entry_set_count(_psUnityLauncherEntry, (counter > 9999) ? 9999 : counter); @@ -327,6 +330,7 @@ void MainWindow::psUpdateCounter() { Libs::unity_launcher_entry_set_count_visible(_psUnityLauncherEntry, FALSE); } } +#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION if (noQtTrayIcon) { if (useAppIndicator) { @@ -416,12 +420,14 @@ void MainWindow::LibsLoaded() { DEBUG_LOG(("Status icon api loaded!")); } +#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION useUnityCount = (Libs::unity_launcher_entry_get_for_desktop_id != nullptr) && (Libs::unity_launcher_entry_set_count != nullptr) && (Libs::unity_launcher_entry_set_count_visible != nullptr); if (useUnityCount) { DEBUG_LOG(("Unity count api loaded!")); } +#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION } void MainWindow::psUpdateDelegate() { @@ -598,6 +604,7 @@ void MainWindow::psCreateTrayIcon() { void MainWindow::psFirstShow() { psCreateTrayIcon(); +#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION if (useUnityCount) { _psUnityLauncherEntry = Libs::unity_launcher_entry_get_for_desktop_id("telegramdesktop.desktop"); if (_psUnityLauncherEntry) { @@ -613,6 +620,7 @@ void MainWindow::psFirstShow() { } else { LOG(("Not using Unity Launcher count.")); } +#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION psUpdateMargins(); diff --git a/Telegram/SourceFiles/platform/platform_file_dialog.h b/Telegram/SourceFiles/platform/platform_file_dialog.h new file mode 100644 index 0000000000..c3d91d84eb --- /dev/null +++ b/Telegram/SourceFiles/platform/platform_file_dialog.h @@ -0,0 +1,61 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop 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 3 of the License, or +(at your option) any later version. + +It 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. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "ui/filedialog.h" + +#ifdef Q_OS_MAC +namespace Platform { + +namespace FileDialog { +inline bool Supported() { + return false; +} +inline bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile) { + return false; +} +} // namespace FileDialog +} // namespace Platform +#elif defined Q_OS_LINUX // Q_OS_MAC +#include "platform/linux/file_dialog_linux.h" +#elif defined Q_OS_WINRT // Q_OS_MAC || Q_OS_LINUX +namespace Platform { +namespace FileDialog { +inline bool Supported() { + return false; +} +inline bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile) { + return false; +} +} // namespace FileDialog +} // namespace Platform +#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT +namespace Platform { +namespace FileDialog { +inline bool Supported() { + return false; +} +inline bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile) { + return false; +} +} // namespace FileDialog +} // namespace Platform +#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || Q_OS_WIN diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 0b8d3696b8..136b26cd8f 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -975,8 +975,13 @@ void DocumentOpenClickHandler::doOpen(DocumentData *data, ActionOnLoad action) { audioPlayer()->play(song); if (App::main()) App::main()->documentPlayProgress(song); } - } else if (data->voice() || data->isVideo()) { - psOpenFile(location.name()); + } else if (data->voice() || data->song() || data->isVideo()) { + auto filepath = location.name(); + if (documentIsValidMediaFile(filepath)) { + psOpenFile(filepath); + } else { + psShowInFolder(filepath); + } if (App::main()) App::main()->mediaMarkRead(data); } else if (data->size < MediaViewImageSizeLimit) { if (!data->data().isEmpty() && playAnimation) { @@ -1270,8 +1275,12 @@ void DocumentData::performActionOnLoad() { psOpenFile(already, true); } } else if (_actionOnLoad == ActionOnLoadOpen || _actionOnLoad == ActionOnLoadPlayInline) { - if (voice() || isVideo()) { - psOpenFile(already); + if (voice() || song() || isVideo()) { + if (documentIsValidMediaFile(already)) { + psOpenFile(already); + } else { + psShowInFolder(already); + } if (App::main()) App::main()->mediaMarkRead(this); } else if (loc.accessEnable()) { if (showImage && QImageReader(loc.name()).canRead()) { diff --git a/Telegram/SourceFiles/ui/filedialog.cpp b/Telegram/SourceFiles/ui/filedialog.cpp index 28e065adfa..f2529eb2b2 100644 --- a/Telegram/SourceFiles/ui/filedialog.cpp +++ b/Telegram/SourceFiles/ui/filedialog.cpp @@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "application.h" #include "localstorage.h" +#include "platform/platform_file_dialog.h" void filedialogInit() { if (cDialogLastPath().isEmpty()) { @@ -69,28 +70,33 @@ void filedialogInit() { } } -// multipleFiles: 1 - multi open, 0 - single open, -1 - single save, -2 - select dir -bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, int multipleFiles, QString startFile = QString()) { +namespace FileDialog { +namespace internal { +bool getFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, FileDialog::internal::Type type, QString startFile = QString()) { filedialogInit(); + if (Platform::FileDialog::Supported()) { + return Platform::FileDialog::Get(files, remoteContent, caption, filter, type, startFile); + } + #if defined Q_OS_LINUX || defined Q_OS_MAC // use native remoteContent = QByteArray(); if (startFile.isEmpty() || startFile.at(0) != '/') { startFile = cDialogLastPath() + '/' + startFile; } - QString file; - if (multipleFiles >= 0) { + QString file; + if (type == Type::ReadFiles) { files = QFileDialog::getOpenFileNames(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter); QString path = files.isEmpty() ? QString() : QFileInfo(files.back()).absoluteDir().absolutePath(); if (!path.isEmpty() && path != cDialogLastPath()) { cSetDialogLastPath(path); Local::writeUserSettings(); } - return !files.isEmpty(); - } else if (multipleFiles < -1) { + return !files.isEmpty(); + } else if (type == Type::ReadFolder) { file = QFileDialog::getExistingDirectory(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile); - } else if (multipleFiles < 0) { + } else if (type == Type::WriteFile) { file = QFileDialog::getSaveFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter); } else { file = QFileDialog::getOpenFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter); @@ -112,11 +118,11 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS // hack for fast non-native dialog create QFileDialog dialog(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, cDialogHelperPathFinal(), filter); - dialog.setModal(true); - if (multipleFiles >= 0) { // open file or files - dialog.setFileMode(multipleFiles ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile); + dialog.setModal(true); + if (type == Type::ReadFile || type == Type::ReadFiles) { + dialog.setFileMode((type == Type::ReadFiles) ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile); dialog.setAcceptMode(QFileDialog::AcceptOpen); - } else if (multipleFiles < -1) { // save dir + } else if (type == Type::ReadFolder) { // save dir dialog.setAcceptMode(QFileDialog::AcceptOpen); dialog.setFileMode(QFileDialog::Directory); dialog.setOption(QFileDialog::ShowDirsOnly); @@ -127,7 +133,7 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS dialog.show(); if (!cDialogLastPath().isEmpty()) dialog.setDirectory(cDialogLastPath()); - if (multipleFiles == -1) { + if (type == Type::WriteFile) { QString toSelect(startFile); #ifdef Q_OS_WIN int32 lastSlash = toSelect.lastIndexOf('/'); @@ -151,12 +157,12 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS } if (res == QDialog::Accepted) { - if (multipleFiles > 0) { + if (type == Type::ReadFiles) { files = dialog.selectedFiles(); } else { files = dialog.selectedFiles().mid(0, 1); } - if (multipleFiles >= 0) { + if (type == Type::ReadFile || type == Type::ReadFiles) { #if defined Q_OS_WIN && !defined Q_OS_WINRT remoteContent = dialog.selectedRemoteContent(); #endif // Q_OS_WIN && !Q_OS_WINRT @@ -169,13 +175,16 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS return false; } +} // namespace internal +} // namespace FileDialog + bool filedialogGetOpenFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter) { - return _filedialogGetFiles(files, remoteContent, caption, filter, 1); + return FileDialog::internal::getFiles(files, remoteContent, caption, filter, FileDialog::internal::Type::ReadFiles); } bool filedialogGetOpenFile(QString &file, QByteArray &remoteContent, const QString &caption, const QString &filter) { QStringList files; - bool result = _filedialogGetFiles(files, remoteContent, caption, filter, 0); + bool result = FileDialog::internal::getFiles(files, remoteContent, caption, filter, FileDialog::internal::Type::ReadFile); file = files.isEmpty() ? QString() : files.at(0); return result; } @@ -183,7 +192,7 @@ bool filedialogGetOpenFile(QString &file, QByteArray &remoteContent, const QStri bool filedialogGetSaveFile(QString &file, const QString &caption, const QString &filter, const QString &startName) { QStringList files; QByteArray remoteContent; - bool result = _filedialogGetFiles(files, remoteContent, caption, filter, -1, startName); + bool result = FileDialog::internal::getFiles(files, remoteContent, caption, filter, FileDialog::internal::Type::WriteFile, startName); file = files.isEmpty() ? QString() : files.at(0); return result; } @@ -191,7 +200,7 @@ bool filedialogGetSaveFile(QString &file, const QString &caption, const QString bool filedialogGetDir(QString &dir, const QString &caption) { QStringList files; QByteArray remoteContent; - bool result = _filedialogGetFiles(files, remoteContent, caption, QString(), -2); + bool result = FileDialog::internal::getFiles(files, remoteContent, caption, QString(), FileDialog::internal::Type::ReadFolder); dir = files.isEmpty() ? QString() : files.at(0); return result; } diff --git a/Telegram/SourceFiles/ui/filedialog.h b/Telegram/SourceFiles/ui/filedialog.h index 9a8317e37b..6ca2bf6930 100644 --- a/Telegram/SourceFiles/ui/filedialog.h +++ b/Telegram/SourceFiles/ui/filedialog.h @@ -32,6 +32,16 @@ QString filedialogDefaultName(const QString &prefix, const QString &extension, c QString filedialogNextFilename(const QString &name, const QString &cur, const QString &path = QString()); namespace FileDialog { +namespace internal { + +enum class Type { + ReadFile, + ReadFiles, + ReadFolder, + WriteFile, +}; + +} // namespace internal using QueryId = uint64; struct QueryUpdate { diff --git a/Telegram/SourceFiles/ui/scrollarea.cpp b/Telegram/SourceFiles/ui/scrollarea.cpp index b0f8c6dd47..9ebd5d32be 100644 --- a/Telegram/SourceFiles/ui/scrollarea.cpp +++ b/Telegram/SourceFiles/ui/scrollarea.cpp @@ -653,6 +653,8 @@ void ScrollArea::moveEvent(QMoveEvent *e) { void ScrollArea::keyPressEvent(QKeyEvent *e) { if ((e->key() == Qt::Key_Up || e->key() == Qt::Key_Down) && e->modifiers().testFlag(Qt::AltModifier)) { e->ignore(); + } else if(e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) { + ((QObject*)widget())->event(e); } else { QScrollArea::keyPressEvent(e); } diff --git a/Telegram/Telegram.pro b/Telegram/Telegram.pro index 8651364b39..cebef44b78 100644 --- a/Telegram/Telegram.pro +++ b/Telegram/Telegram.pro @@ -3,60 +3,60 @@ QT += core gui network widgets CONFIG += plugin static c++14 CONFIG(debug, debug|release) { - DEFINES += _DEBUG - OBJECTS_DIR = ./../DebugIntermediate - MOC_DIR = ./GeneratedFiles/Debug - RCC_DIR = ./GeneratedFiles - DESTDIR = ./../Debug + DEFINES += _DEBUG + OBJECTS_DIR = ./../DebugIntermediate + MOC_DIR = ./GeneratedFiles/Debug + RCC_DIR = ./GeneratedFiles + DESTDIR = ./../Debug } CONFIG(release, debug|release) { - DEFINES += CUSTOM_API_ID - OBJECTS_DIR = ./../ReleaseIntermediate - MOC_DIR = ./GeneratedFiles/Release - RCC_DIR = ./GeneratedFiles - DESTDIR = ./../Release + DEFINES += CUSTOM_API_ID + OBJECTS_DIR = ./../ReleaseIntermediate + MOC_DIR = ./GeneratedFiles/Release + RCC_DIR = ./GeneratedFiles + DESTDIR = ./../Release } macx { - QMAKE_INFO_PLIST = ./SourceFiles/Telegram.plist - QMAKE_LFLAGS += -framework Cocoa + QMAKE_INFO_PLIST = ./SourceFiles/Telegram.plist + QMAKE_LFLAGS += -framework Cocoa } linux { - SOURCES += ./SourceFiles/pspecific_linux.cpp - HEADERS += ./SourceFiles/pspecific_linux.h + SOURCES += ./SourceFiles/pspecific_linux.cpp + HEADERS += ./SourceFiles/pspecific_linux.h } CONFIG(debug, debug|release) { - codegen_style.target = style_target - codegen_style.depends = FORCE - codegen_style.commands = ./../codegen/Debug/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild + codegen_style.target = style_target + codegen_style.depends = FORCE + codegen_style.commands = ./../codegen/Debug/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild - codegen_numbers.target = numbers_target - codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt - codegen_numbers.commands = ./../codegen/Debug/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt" + codegen_numbers.target = numbers_target + codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt + codegen_numbers.commands = ./../codegen/Debug/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt" - codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Debug/codegen_numbers "-o./../Linux/DebugIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/DebugIntermediate + codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Debug/codegen_numbers "-o./../Linux/DebugIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/DebugIntermediate - codegen_lang.target = lang_target - codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings - codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../DebugLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto + codegen_lang.target = lang_target + codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings + codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../DebugLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto } CONFIG(release, debug|release) { - codegen_style.target = style_target - codegen_style.depends = FORCE - codegen_style.commands = ./../codegen/Release/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild + codegen_style.target = style_target + codegen_style.depends = FORCE + codegen_style.commands = ./../codegen/Release/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild - codegen_numbers.target = numbers_target - codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt - codegen_numbers.commands = ./../codegen/Release/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt" + codegen_numbers.target = numbers_target + codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt + codegen_numbers.commands = ./../codegen/Release/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt" - codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Release/codegen_numbers "-o./../Linux/ReleaseIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/ReleaseIntermediate + codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Release/codegen_numbers "-o./../Linux/ReleaseIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/ReleaseIntermediate - codegen_lang.target = lang_target - codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings - codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../ReleaseLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto + codegen_lang.target = lang_target + codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings + codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../ReleaseLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto } file_style_basic.target = GeneratedFiles/styles/style_basic.cpp @@ -73,374 +73,379 @@ file_style_profile.target = GeneratedFiles/styles/style_profile.cpp file_style_profile.depends = style_target QMAKE_EXTRA_TARGETS += codegen_style codegen_numbers codegen_lang \ - file_style_basic file_style_basic_types file_style_overview \ - file_style_dialogs file_style_history file_style_profile + file_style_basic file_style_basic_types file_style_overview \ + file_style_dialogs file_style_history file_style_profile PRE_TARGETDEPS += style_target numbers_target lang_target unix { - linux-g++:QMAKE_TARGET.arch = $$QMAKE_HOST.arch - linux-g++-32:QMAKE_TARGET.arch = x86 - linux-g++-64:QMAKE_TARGET.arch = x86_64 + linux-g++:QMAKE_TARGET.arch = $$QMAKE_HOST.arch + linux-g++-32:QMAKE_TARGET.arch = x86 + linux-g++-64:QMAKE_TARGET.arch = x86_64 - contains(QMAKE_TARGET.arch, x86_64) { - DEFINES += Q_OS_LINUX64 - } else { - DEFINES += Q_OS_LINUX32 - } + contains(QMAKE_TARGET.arch, x86_64) { + DEFINES += Q_OS_LINUX64 + } else { + DEFINES += Q_OS_LINUX32 + } } SOURCES += \ - ./GeneratedFiles/lang_auto.cpp \ - ./GeneratedFiles/numbers.cpp \ - ./GeneratedFiles/styles/style_basic.cpp \ - ./GeneratedFiles/styles/style_basic_types.cpp \ - ./GeneratedFiles/styles/style_dialogs.cpp \ - ./GeneratedFiles/styles/style_history.cpp \ - ./GeneratedFiles/styles/style_overview.cpp \ - ./GeneratedFiles/styles/style_profile.cpp \ - ./SourceFiles/main.cpp \ - ./SourceFiles/stdafx.cpp \ - ./SourceFiles/apiwrap.cpp \ - ./SourceFiles/app.cpp \ - ./SourceFiles/application.cpp \ - ./SourceFiles/audio.cpp \ - ./SourceFiles/autoupdater.cpp \ - ./SourceFiles/dialogswidget.cpp \ - ./SourceFiles/dropdown.cpp \ - ./SourceFiles/facades.cpp \ - ./SourceFiles/fileuploader.cpp \ - ./SourceFiles/history.cpp \ - ./SourceFiles/historywidget.cpp \ - ./SourceFiles/lang.cpp \ - ./SourceFiles/langloaderplain.cpp \ - ./SourceFiles/layerwidget.cpp \ - ./SourceFiles/layout.cpp \ - ./SourceFiles/mediaview.cpp \ - ./SourceFiles/observer_peer.cpp \ - ./SourceFiles/overviewwidget.cpp \ - ./SourceFiles/passcodewidget.cpp \ - ./SourceFiles/playerwidget.cpp \ - ./SourceFiles/localimageloader.cpp \ - ./SourceFiles/localstorage.cpp \ - ./SourceFiles/logs.cpp \ - ./SourceFiles/mainwidget.cpp \ - ./SourceFiles/settings.cpp \ - ./SourceFiles/settingswidget.cpp \ - ./SourceFiles/shortcuts.cpp \ - ./SourceFiles/structs.cpp \ - ./SourceFiles/sysbuttons.cpp \ - ./SourceFiles/title.cpp \ - ./SourceFiles/mainwindow.cpp \ - ./SourceFiles/boxes/aboutbox.cpp \ - ./SourceFiles/boxes/abstractbox.cpp \ - ./SourceFiles/boxes/addcontactbox.cpp \ - ./SourceFiles/boxes/autolockbox.cpp \ - ./SourceFiles/boxes/backgroundbox.cpp \ - ./SourceFiles/boxes/confirmbox.cpp \ - ./SourceFiles/boxes/connectionbox.cpp \ - ./SourceFiles/boxes/contactsbox.cpp \ - ./SourceFiles/boxes/downloadpathbox.cpp \ - ./SourceFiles/boxes/emojibox.cpp \ - ./SourceFiles/boxes/languagebox.cpp \ - ./SourceFiles/boxes/passcodebox.cpp \ - ./SourceFiles/boxes/photocropbox.cpp \ - ./SourceFiles/boxes/photosendbox.cpp \ - ./SourceFiles/boxes/report_box.cpp \ - ./SourceFiles/boxes/sessionsbox.cpp \ - ./SourceFiles/boxes/stickersetbox.cpp \ - ./SourceFiles/boxes/usernamebox.cpp \ - ./SourceFiles/core/basic_types.cpp \ - ./SourceFiles/core/click_handler.cpp \ - ./SourceFiles/core/click_handler_types.cpp \ - ./SourceFiles/core/observer.cpp \ - ./SourceFiles/data/data_abstract_structure.cpp \ - ./SourceFiles/data/data_drafts.cpp \ - ./SourceFiles/dialogs/dialogs_indexed_list.cpp \ - ./SourceFiles/dialogs/dialogs_layout.cpp \ - ./SourceFiles/dialogs/dialogs_list.cpp \ - ./SourceFiles/dialogs/dialogs_row.cpp \ - ./SourceFiles/history/field_autocomplete.cpp \ - ./SourceFiles/history/history_service_layout.cpp \ - ./SourceFiles/inline_bots/inline_bot_layout_internal.cpp \ - ./SourceFiles/inline_bots/inline_bot_layout_item.cpp \ - ./SourceFiles/inline_bots/inline_bot_result.cpp \ - ./SourceFiles/inline_bots/inline_bot_send_data.cpp \ - ./SourceFiles/intro/introwidget.cpp \ - ./SourceFiles/intro/introcode.cpp \ - ./SourceFiles/intro/introphone.cpp \ - ./SourceFiles/intro/intropwdcheck.cpp \ - ./SourceFiles/intro/introsignup.cpp \ - ./SourceFiles/intro/introstart.cpp \ - ./SourceFiles/mtproto/facade.cpp \ - ./SourceFiles/mtproto/auth_key.cpp \ - ./SourceFiles/mtproto/connection.cpp \ - ./SourceFiles/mtproto/connection_abstract.cpp \ - ./SourceFiles/mtproto/connection_auto.cpp \ - ./SourceFiles/mtproto/connection_http.cpp \ - ./SourceFiles/mtproto/connection_tcp.cpp \ - ./SourceFiles/mtproto/core_types.cpp \ - ./SourceFiles/mtproto/dcenter.cpp \ - ./SourceFiles/mtproto/file_download.cpp \ - ./SourceFiles/mtproto/rsa_public_key.cpp \ - ./SourceFiles/mtproto/rpc_sender.cpp \ - ./SourceFiles/mtproto/scheme_auto.cpp \ - ./SourceFiles/mtproto/session.cpp \ - ./SourceFiles/overview/overview_layout.cpp \ + ./GeneratedFiles/lang_auto.cpp \ + ./GeneratedFiles/numbers.cpp \ + ./GeneratedFiles/styles/style_basic.cpp \ + ./GeneratedFiles/styles/style_basic_types.cpp \ + ./GeneratedFiles/styles/style_dialogs.cpp \ + ./GeneratedFiles/styles/style_history.cpp \ + ./GeneratedFiles/styles/style_overview.cpp \ + ./GeneratedFiles/styles/style_profile.cpp \ + ./SourceFiles/main.cpp \ + ./SourceFiles/stdafx.cpp \ + ./SourceFiles/apiwrap.cpp \ + ./SourceFiles/app.cpp \ + ./SourceFiles/application.cpp \ + ./SourceFiles/audio.cpp \ + ./SourceFiles/autoupdater.cpp \ + ./SourceFiles/dialogswidget.cpp \ + ./SourceFiles/dropdown.cpp \ + ./SourceFiles/facades.cpp \ + ./SourceFiles/fileuploader.cpp \ + ./SourceFiles/history.cpp \ + ./SourceFiles/historywidget.cpp \ + ./SourceFiles/lang.cpp \ + ./SourceFiles/langloaderplain.cpp \ + ./SourceFiles/layerwidget.cpp \ + ./SourceFiles/layout.cpp \ + ./SourceFiles/mediaview.cpp \ + ./SourceFiles/observer_peer.cpp \ + ./SourceFiles/overviewwidget.cpp \ + ./SourceFiles/passcodewidget.cpp \ + ./SourceFiles/playerwidget.cpp \ + ./SourceFiles/localimageloader.cpp \ + ./SourceFiles/localstorage.cpp \ + ./SourceFiles/logs.cpp \ + ./SourceFiles/mainwidget.cpp \ + ./SourceFiles/settings.cpp \ + ./SourceFiles/settingswidget.cpp \ + ./SourceFiles/shortcuts.cpp \ + ./SourceFiles/structs.cpp \ + ./SourceFiles/sysbuttons.cpp \ + ./SourceFiles/title.cpp \ + ./SourceFiles/mainwindow.cpp \ + ./SourceFiles/boxes/aboutbox.cpp \ + ./SourceFiles/boxes/abstractbox.cpp \ + ./SourceFiles/boxes/addcontactbox.cpp \ + ./SourceFiles/boxes/autolockbox.cpp \ + ./SourceFiles/boxes/backgroundbox.cpp \ + ./SourceFiles/boxes/confirmbox.cpp \ + ./SourceFiles/boxes/connectionbox.cpp \ + ./SourceFiles/boxes/contactsbox.cpp \ + ./SourceFiles/boxes/downloadpathbox.cpp \ + ./SourceFiles/boxes/emojibox.cpp \ + ./SourceFiles/boxes/languagebox.cpp \ + ./SourceFiles/boxes/passcodebox.cpp \ + ./SourceFiles/boxes/photocropbox.cpp \ + ./SourceFiles/boxes/photosendbox.cpp \ + ./SourceFiles/boxes/report_box.cpp \ + ./SourceFiles/boxes/sessionsbox.cpp \ + ./SourceFiles/boxes/stickersetbox.cpp \ + ./SourceFiles/boxes/usernamebox.cpp \ + ./SourceFiles/core/basic_types.cpp \ + ./SourceFiles/core/click_handler.cpp \ + ./SourceFiles/core/click_handler_types.cpp \ + ./SourceFiles/core/observer.cpp \ + ./SourceFiles/data/data_abstract_structure.cpp \ + ./SourceFiles/data/data_drafts.cpp \ + ./SourceFiles/dialogs/dialogs_indexed_list.cpp \ + ./SourceFiles/dialogs/dialogs_layout.cpp \ + ./SourceFiles/dialogs/dialogs_list.cpp \ + ./SourceFiles/dialogs/dialogs_row.cpp \ + ./SourceFiles/history/field_autocomplete.cpp \ + ./SourceFiles/history/history_service_layout.cpp \ + ./SourceFiles/inline_bots/inline_bot_layout_internal.cpp \ + ./SourceFiles/inline_bots/inline_bot_layout_item.cpp \ + ./SourceFiles/inline_bots/inline_bot_result.cpp \ + ./SourceFiles/inline_bots/inline_bot_send_data.cpp \ + ./SourceFiles/intro/introwidget.cpp \ + ./SourceFiles/intro/introcode.cpp \ + ./SourceFiles/intro/introphone.cpp \ + ./SourceFiles/intro/intropwdcheck.cpp \ + ./SourceFiles/intro/introsignup.cpp \ + ./SourceFiles/intro/introstart.cpp \ + ./SourceFiles/mtproto/facade.cpp \ + ./SourceFiles/mtproto/auth_key.cpp \ + ./SourceFiles/mtproto/connection.cpp \ + ./SourceFiles/mtproto/connection_abstract.cpp \ + ./SourceFiles/mtproto/connection_auto.cpp \ + ./SourceFiles/mtproto/connection_http.cpp \ + ./SourceFiles/mtproto/connection_tcp.cpp \ + ./SourceFiles/mtproto/core_types.cpp \ + ./SourceFiles/mtproto/dcenter.cpp \ + ./SourceFiles/mtproto/file_download.cpp \ + ./SourceFiles/mtproto/rsa_public_key.cpp \ + ./SourceFiles/mtproto/rpc_sender.cpp \ + ./SourceFiles/mtproto/scheme_auto.cpp \ + ./SourceFiles/mtproto/session.cpp \ + ./SourceFiles/overview/overview_layout.cpp \ + ./SourceFiles/platform/linux/linux_gdk_helper.cpp \ ./SourceFiles/platform/linux/linux_libs.cpp \ - ./SourceFiles/platform/linux/main_window_linux.cpp \ - ./SourceFiles/profile/profile_actions_widget.cpp \ - ./SourceFiles/profile/profile_block_widget.cpp \ - ./SourceFiles/profile/profile_cover_drop_area.cpp \ - ./SourceFiles/profile/profile_cover.cpp \ - ./SourceFiles/profile/profile_fixed_bar.cpp \ - ./SourceFiles/profile/profile_info_widget.cpp \ - ./SourceFiles/profile/profile_inner_widget.cpp \ - ./SourceFiles/profile/profile_invite_link_widget.cpp \ - ./SourceFiles/profile/profile_members_widget.cpp \ - ./SourceFiles/profile/profile_section_memento.cpp \ - ./SourceFiles/profile/profile_settings_widget.cpp \ - ./SourceFiles/profile/profile_shared_media_widget.cpp \ - ./SourceFiles/profile/profile_userpic_button.cpp \ - ./SourceFiles/profile/profile_widget.cpp \ - ./SourceFiles/serialize/serialize_common.cpp \ - ./SourceFiles/serialize/serialize_document.cpp \ - ./SourceFiles/ui/buttons/history_down_button.cpp \ - ./SourceFiles/ui/buttons/left_outline_button.cpp \ - ./SourceFiles/ui/buttons/peer_avatar_button.cpp \ - ./SourceFiles/ui/buttons/round_button.cpp \ - ./SourceFiles/ui/style/style_core.cpp \ - ./SourceFiles/ui/style/style_core_color.cpp \ - ./SourceFiles/ui/style/style_core_font.cpp \ - ./SourceFiles/ui/style/style_core_icon.cpp \ - ./SourceFiles/ui/style/style_core_types.cpp \ - ./SourceFiles/ui/text/text.cpp \ - ./SourceFiles/ui/text/text_block.cpp \ - ./SourceFiles/ui/text/text_entity.cpp \ - ./SourceFiles/ui/toast/toast.cpp \ - ./SourceFiles/ui/toast/toast_manager.cpp \ - ./SourceFiles/ui/toast/toast_widget.cpp \ - ./SourceFiles/ui/animation.cpp \ - ./SourceFiles/ui/boxshadow.cpp \ - ./SourceFiles/ui/button.cpp \ - ./SourceFiles/ui/popupmenu.cpp \ - ./SourceFiles/ui/countryinput.cpp \ - ./SourceFiles/ui/emoji_config.cpp \ - ./SourceFiles/ui/filedialog.cpp \ - ./SourceFiles/ui/flatbutton.cpp \ - ./SourceFiles/ui/flatcheckbox.cpp \ - ./SourceFiles/ui/flatinput.cpp \ - ./SourceFiles/ui/flatlabel.cpp \ - ./SourceFiles/ui/flattextarea.cpp \ - ./SourceFiles/ui/images.cpp \ - ./SourceFiles/ui/inner_dropdown.cpp \ - ./SourceFiles/ui/scrollarea.cpp \ - ./SourceFiles/ui/twidget.cpp \ - ./SourceFiles/window/main_window.cpp \ - ./SourceFiles/window/section_widget.cpp \ - ./SourceFiles/window/slide_animation.cpp \ - ./SourceFiles/window/top_bar_widget.cpp + ./SourceFiles/platform/linux/file_dialog_linux.cpp \ + ./SourceFiles/platform/linux/main_window_linux.cpp \ + ./SourceFiles/profile/profile_actions_widget.cpp \ + ./SourceFiles/profile/profile_block_widget.cpp \ + ./SourceFiles/profile/profile_cover_drop_area.cpp \ + ./SourceFiles/profile/profile_cover.cpp \ + ./SourceFiles/profile/profile_fixed_bar.cpp \ + ./SourceFiles/profile/profile_info_widget.cpp \ + ./SourceFiles/profile/profile_inner_widget.cpp \ + ./SourceFiles/profile/profile_invite_link_widget.cpp \ + ./SourceFiles/profile/profile_members_widget.cpp \ + ./SourceFiles/profile/profile_section_memento.cpp \ + ./SourceFiles/profile/profile_settings_widget.cpp \ + ./SourceFiles/profile/profile_shared_media_widget.cpp \ + ./SourceFiles/profile/profile_userpic_button.cpp \ + ./SourceFiles/profile/profile_widget.cpp \ + ./SourceFiles/serialize/serialize_common.cpp \ + ./SourceFiles/serialize/serialize_document.cpp \ + ./SourceFiles/ui/buttons/history_down_button.cpp \ + ./SourceFiles/ui/buttons/left_outline_button.cpp \ + ./SourceFiles/ui/buttons/peer_avatar_button.cpp \ + ./SourceFiles/ui/buttons/round_button.cpp \ + ./SourceFiles/ui/style/style_core.cpp \ + ./SourceFiles/ui/style/style_core_color.cpp \ + ./SourceFiles/ui/style/style_core_font.cpp \ + ./SourceFiles/ui/style/style_core_icon.cpp \ + ./SourceFiles/ui/style/style_core_types.cpp \ + ./SourceFiles/ui/text/text.cpp \ + ./SourceFiles/ui/text/text_block.cpp \ + ./SourceFiles/ui/text/text_entity.cpp \ + ./SourceFiles/ui/toast/toast.cpp \ + ./SourceFiles/ui/toast/toast_manager.cpp \ + ./SourceFiles/ui/toast/toast_widget.cpp \ + ./SourceFiles/ui/animation.cpp \ + ./SourceFiles/ui/boxshadow.cpp \ + ./SourceFiles/ui/button.cpp \ + ./SourceFiles/ui/popupmenu.cpp \ + ./SourceFiles/ui/countryinput.cpp \ + ./SourceFiles/ui/emoji_config.cpp \ + ./SourceFiles/ui/filedialog.cpp \ + ./SourceFiles/ui/flatbutton.cpp \ + ./SourceFiles/ui/flatcheckbox.cpp \ + ./SourceFiles/ui/flatinput.cpp \ + ./SourceFiles/ui/flatlabel.cpp \ + ./SourceFiles/ui/flattextarea.cpp \ + ./SourceFiles/ui/images.cpp \ + ./SourceFiles/ui/inner_dropdown.cpp \ + ./SourceFiles/ui/scrollarea.cpp \ + ./SourceFiles/ui/twidget.cpp \ + ./SourceFiles/window/main_window.cpp \ + ./SourceFiles/window/section_widget.cpp \ + ./SourceFiles/window/slide_animation.cpp \ + ./SourceFiles/window/top_bar_widget.cpp HEADERS += \ - ./GeneratedFiles/lang_auto.h \ - ./GeneratedFiles/numbers.h \ - ./GeneratedFiles/styles/style_basic.h \ - ./GeneratedFiles/styles/style_basic_types.h \ - ./GeneratedFiles/styles/style_dialogs.h \ - ./GeneratedFiles/styles/style_history.h \ - ./GeneratedFiles/styles/style_overview.h \ - ./GeneratedFiles/styles/style_profile.h \ - ./SourceFiles/stdafx.h \ - ./SourceFiles/apiwrap.h \ - ./SourceFiles/app.h \ - ./SourceFiles/application.h \ - ./SourceFiles/audio.h \ - ./SourceFiles/autoupdater.h \ - ./SourceFiles/config.h \ - ./SourceFiles/countries.h \ - ./SourceFiles/dialogswidget.h \ - ./SourceFiles/dropdown.h \ - ./SourceFiles/facades.h \ - ./SourceFiles/fileuploader.h \ - ./SourceFiles/history.h \ - ./SourceFiles/historywidget.h \ - ./SourceFiles/lang.h \ - ./SourceFiles/langloaderplain.h \ - ./SourceFiles/layerwidget.h \ - ./SourceFiles/layout.h \ - ./SourceFiles/mediaview.h \ - ./SourceFiles/observer_peer.h \ - ./SourceFiles/overviewwidget.h \ - ./SourceFiles/passcodewidget.h \ - ./SourceFiles/playerwidget.h \ - ./SourceFiles/localimageloader.h \ - ./SourceFiles/localstorage.h \ - ./SourceFiles/logs.h \ - ./SourceFiles/mainwidget.h \ - ./SourceFiles/settings.h \ - ./SourceFiles/settingswidget.h \ - ./SourceFiles/shortcuts.h \ - ./SourceFiles/structs.h \ - ./SourceFiles/sysbuttons.h \ - ./SourceFiles/title.h \ - ./SourceFiles/mainwindow.h \ - ./SourceFiles/boxes/aboutbox.h \ - ./SourceFiles/boxes/abstractbox.h \ - ./SourceFiles/boxes/addcontactbox.h \ - ./SourceFiles/boxes/autolockbox.h \ - ./SourceFiles/boxes/backgroundbox.h \ - ./SourceFiles/boxes/confirmbox.h \ - ./SourceFiles/boxes/connectionbox.h \ - ./SourceFiles/boxes/contactsbox.h \ - ./SourceFiles/boxes/downloadpathbox.h \ - ./SourceFiles/boxes/emojibox.h \ - ./SourceFiles/boxes/languagebox.h \ - ./SourceFiles/boxes/passcodebox.h \ - ./SourceFiles/boxes/photocropbox.h \ - ./SourceFiles/boxes/photosendbox.h \ - ./SourceFiles/boxes/report_box.h \ - ./SourceFiles/boxes/sessionsbox.h \ - ./SourceFiles/boxes/stickersetbox.h \ - ./SourceFiles/boxes/usernamebox.h \ - ./SourceFiles/core/basic_types.h \ - ./SourceFiles/core/click_handler.h \ - ./SourceFiles/core/click_handler_types.h \ - ./SourceFiles/core/observer.h \ - ./SourceFiles/core/vector_of_moveable.h \ + ./GeneratedFiles/lang_auto.h \ + ./GeneratedFiles/numbers.h \ + ./GeneratedFiles/styles/style_basic.h \ + ./GeneratedFiles/styles/style_basic_types.h \ + ./GeneratedFiles/styles/style_dialogs.h \ + ./GeneratedFiles/styles/style_history.h \ + ./GeneratedFiles/styles/style_overview.h \ + ./GeneratedFiles/styles/style_profile.h \ + ./SourceFiles/stdafx.h \ + ./SourceFiles/apiwrap.h \ + ./SourceFiles/app.h \ + ./SourceFiles/application.h \ + ./SourceFiles/audio.h \ + ./SourceFiles/autoupdater.h \ + ./SourceFiles/config.h \ + ./SourceFiles/countries.h \ + ./SourceFiles/dialogswidget.h \ + ./SourceFiles/dropdown.h \ + ./SourceFiles/facades.h \ + ./SourceFiles/fileuploader.h \ + ./SourceFiles/history.h \ + ./SourceFiles/historywidget.h \ + ./SourceFiles/lang.h \ + ./SourceFiles/langloaderplain.h \ + ./SourceFiles/layerwidget.h \ + ./SourceFiles/layout.h \ + ./SourceFiles/mediaview.h \ + ./SourceFiles/observer_peer.h \ + ./SourceFiles/overviewwidget.h \ + ./SourceFiles/passcodewidget.h \ + ./SourceFiles/playerwidget.h \ + ./SourceFiles/localimageloader.h \ + ./SourceFiles/localstorage.h \ + ./SourceFiles/logs.h \ + ./SourceFiles/mainwidget.h \ + ./SourceFiles/settings.h \ + ./SourceFiles/settingswidget.h \ + ./SourceFiles/shortcuts.h \ + ./SourceFiles/structs.h \ + ./SourceFiles/sysbuttons.h \ + ./SourceFiles/title.h \ + ./SourceFiles/mainwindow.h \ + ./SourceFiles/boxes/aboutbox.h \ + ./SourceFiles/boxes/abstractbox.h \ + ./SourceFiles/boxes/addcontactbox.h \ + ./SourceFiles/boxes/autolockbox.h \ + ./SourceFiles/boxes/backgroundbox.h \ + ./SourceFiles/boxes/confirmbox.h \ + ./SourceFiles/boxes/connectionbox.h \ + ./SourceFiles/boxes/contactsbox.h \ + ./SourceFiles/boxes/downloadpathbox.h \ + ./SourceFiles/boxes/emojibox.h \ + ./SourceFiles/boxes/languagebox.h \ + ./SourceFiles/boxes/passcodebox.h \ + ./SourceFiles/boxes/photocropbox.h \ + ./SourceFiles/boxes/photosendbox.h \ + ./SourceFiles/boxes/report_box.h \ + ./SourceFiles/boxes/sessionsbox.h \ + ./SourceFiles/boxes/stickersetbox.h \ + ./SourceFiles/boxes/usernamebox.h \ + ./SourceFiles/core/basic_types.h \ + ./SourceFiles/core/click_handler.h \ + ./SourceFiles/core/click_handler_types.h \ + ./SourceFiles/core/observer.h \ + ./SourceFiles/core/vector_of_moveable.h \ ./SourceFiles/core/version.h \ - ./SourceFiles/data/data_abstract_structure.h \ - ./SourceFiles/data/data_drafts.h \ - ./SourceFiles/dialogs/dialogs_common.h \ - ./SourceFiles/dialogs/dialogs_indexed_list.h \ - ./SourceFiles/dialogs/dialogs_layout.h \ - ./SourceFiles/dialogs/dialogs_list.h \ - ./SourceFiles/dialogs/dialogs_row.h \ - ./SourceFiles/history/field_autocomplete.h \ - ./SourceFiles/history/history_common.h \ - ./SourceFiles/history/history_service_layout.h \ - ./SourceFiles/inline_bots/inline_bot_layout_internal.h \ - ./SourceFiles/inline_bots/inline_bot_layout_item.h \ - ./SourceFiles/inline_bots/inline_bot_result.h \ - ./SourceFiles/inline_bots/inline_bot_send_data.h \ - ./SourceFiles/intro/introwidget.h \ - ./SourceFiles/intro/introcode.h \ - ./SourceFiles/intro/introphone.h \ - ./SourceFiles/intro/intropwdcheck.h \ - ./SourceFiles/intro/introsignup.h \ - ./SourceFiles/intro/introstart.h \ - ./SourceFiles/mtproto/facade.h \ - ./SourceFiles/mtproto/auth_key.h \ - ./SourceFiles/mtproto/connection.h \ - ./SourceFiles/mtproto/connection_abstract.h \ - ./SourceFiles/mtproto/connection_auto.h \ - ./SourceFiles/mtproto/connection_http.h \ - ./SourceFiles/mtproto/connection_tcp.h \ - ./SourceFiles/mtproto/core_types.h \ - ./SourceFiles/mtproto/dcenter.h \ - ./SourceFiles/mtproto/file_download.h \ - ./SourceFiles/mtproto/rsa_public_key.h \ - ./SourceFiles/mtproto/rpc_sender.h \ - ./SourceFiles/mtproto/scheme_auto.h \ - ./SourceFiles/mtproto/session.h \ - ./SourceFiles/overview/overview_layout.h \ - ./SourceFiles/platform/platform_main_window.h \ + ./SourceFiles/data/data_abstract_structure.h \ + ./SourceFiles/data/data_drafts.h \ + ./SourceFiles/dialogs/dialogs_common.h \ + ./SourceFiles/dialogs/dialogs_indexed_list.h \ + ./SourceFiles/dialogs/dialogs_layout.h \ + ./SourceFiles/dialogs/dialogs_list.h \ + ./SourceFiles/dialogs/dialogs_row.h \ + ./SourceFiles/history/field_autocomplete.h \ + ./SourceFiles/history/history_common.h \ + ./SourceFiles/history/history_service_layout.h \ + ./SourceFiles/inline_bots/inline_bot_layout_internal.h \ + ./SourceFiles/inline_bots/inline_bot_layout_item.h \ + ./SourceFiles/inline_bots/inline_bot_result.h \ + ./SourceFiles/inline_bots/inline_bot_send_data.h \ + ./SourceFiles/intro/introwidget.h \ + ./SourceFiles/intro/introcode.h \ + ./SourceFiles/intro/introphone.h \ + ./SourceFiles/intro/intropwdcheck.h \ + ./SourceFiles/intro/introsignup.h \ + ./SourceFiles/intro/introstart.h \ + ./SourceFiles/mtproto/facade.h \ + ./SourceFiles/mtproto/auth_key.h \ + ./SourceFiles/mtproto/connection.h \ + ./SourceFiles/mtproto/connection_abstract.h \ + ./SourceFiles/mtproto/connection_auto.h \ + ./SourceFiles/mtproto/connection_http.h \ + ./SourceFiles/mtproto/connection_tcp.h \ + ./SourceFiles/mtproto/core_types.h \ + ./SourceFiles/mtproto/dcenter.h \ + ./SourceFiles/mtproto/file_download.h \ + ./SourceFiles/mtproto/rsa_public_key.h \ + ./SourceFiles/mtproto/rpc_sender.h \ + ./SourceFiles/mtproto/scheme_auto.h \ + ./SourceFiles/mtproto/session.h \ + ./SourceFiles/overview/overview_layout.h \ + ./SourceFiles/platform/platform_file_dialog.h \ + ./SourceFiles/platform/platform_main_window.h \ + ./SourceFiles/platform/linux/linux_gdk_helper.h \ ./SourceFiles/platform/linux/linux_libs.h \ - ./SourceFiles/platform/linux/main_window_linux.h \ - ./SourceFiles/profile/profile_actions_widget.h \ - ./SourceFiles/profile/profile_block_widget.h \ - ./SourceFiles/profile/profile_cover_drop_area.h \ - ./SourceFiles/profile/profile_cover.h \ - ./SourceFiles/profile/profile_fixed_bar.h \ - ./SourceFiles/profile/profile_info_widget.h \ - ./SourceFiles/profile/profile_inner_widget.h \ - ./SourceFiles/profile/profile_invite_link_widget.h \ - ./SourceFiles/profile/profile_members_widget.h \ - ./SourceFiles/profile/profile_section_memento.h \ - ./SourceFiles/profile/profile_settings_widget.h \ - ./SourceFiles/profile/profile_shared_media_widget.h \ - ./SourceFiles/profile/profile_userpic_button.h \ - ./SourceFiles/profile/profile_widget.h \ - ./SourceFiles/pspecific.h \ - ./SourceFiles/serialize/serialize_common.h \ - ./SourceFiles/serialize/serialize_document.h \ - ./SourceFiles/ui/buttons/history_down_button.h \ - ./SourceFiles/ui/buttons/left_outline_button.h \ - ./SourceFiles/ui/buttons/peer_avatar_button.h \ - ./SourceFiles/ui/buttons/round_button.h \ - ./SourceFiles/ui/style/style_core.h \ - ./SourceFiles/ui/style/style_core_color.h \ - ./SourceFiles/ui/style/style_core_font.h \ - ./SourceFiles/ui/style/style_core_icon.h \ - ./SourceFiles/ui/style/style_core_types.h \ - ./SourceFiles/ui/text/text.h \ - ./SourceFiles/ui/text/text_block.h \ - ./SourceFiles/ui/text/text_entity.h \ - ./SourceFiles/ui/toast/toast.h \ - ./SourceFiles/ui/toast/toast_manager.h \ - ./SourceFiles/ui/toast/toast_widget.h \ - ./SourceFiles/ui/animation.h \ - ./SourceFiles/ui/boxshadow.h \ - ./SourceFiles/ui/button.h \ - ./SourceFiles/ui/popupmenu.h \ - ./SourceFiles/ui/countryinput.h \ - ./SourceFiles/ui/emoji_config.h \ - ./SourceFiles/ui/filedialog.h \ - ./SourceFiles/ui/flatbutton.h \ - ./SourceFiles/ui/flatcheckbox.h \ - ./SourceFiles/ui/flatinput.h \ - ./SourceFiles/ui/flatlabel.h \ - ./SourceFiles/ui/flattextarea.h \ - ./SourceFiles/ui/images.h \ - ./SourceFiles/ui/inner_dropdown.h \ - ./SourceFiles/ui/scrollarea.h \ - ./SourceFiles/ui/twidget.h \ - ./SourceFiles/window/main_window.h \ - ./SourceFiles/window/section_memento.h \ - ./SourceFiles/window/section_widget.h \ - ./SourceFiles/window/slide_animation.h \ - ./SourceFiles/window/top_bar_widget.h + ./SourceFiles/platform/linux/file_dialog_linux.h \ + ./SourceFiles/platform/linux/main_window_linux.h \ + ./SourceFiles/profile/profile_actions_widget.h \ + ./SourceFiles/profile/profile_block_widget.h \ + ./SourceFiles/profile/profile_cover_drop_area.h \ + ./SourceFiles/profile/profile_cover.h \ + ./SourceFiles/profile/profile_fixed_bar.h \ + ./SourceFiles/profile/profile_info_widget.h \ + ./SourceFiles/profile/profile_inner_widget.h \ + ./SourceFiles/profile/profile_invite_link_widget.h \ + ./SourceFiles/profile/profile_members_widget.h \ + ./SourceFiles/profile/profile_section_memento.h \ + ./SourceFiles/profile/profile_settings_widget.h \ + ./SourceFiles/profile/profile_shared_media_widget.h \ + ./SourceFiles/profile/profile_userpic_button.h \ + ./SourceFiles/profile/profile_widget.h \ + ./SourceFiles/pspecific.h \ + ./SourceFiles/serialize/serialize_common.h \ + ./SourceFiles/serialize/serialize_document.h \ + ./SourceFiles/ui/buttons/history_down_button.h \ + ./SourceFiles/ui/buttons/left_outline_button.h \ + ./SourceFiles/ui/buttons/peer_avatar_button.h \ + ./SourceFiles/ui/buttons/round_button.h \ + ./SourceFiles/ui/style/style_core.h \ + ./SourceFiles/ui/style/style_core_color.h \ + ./SourceFiles/ui/style/style_core_font.h \ + ./SourceFiles/ui/style/style_core_icon.h \ + ./SourceFiles/ui/style/style_core_types.h \ + ./SourceFiles/ui/text/text.h \ + ./SourceFiles/ui/text/text_block.h \ + ./SourceFiles/ui/text/text_entity.h \ + ./SourceFiles/ui/toast/toast.h \ + ./SourceFiles/ui/toast/toast_manager.h \ + ./SourceFiles/ui/toast/toast_widget.h \ + ./SourceFiles/ui/animation.h \ + ./SourceFiles/ui/boxshadow.h \ + ./SourceFiles/ui/button.h \ + ./SourceFiles/ui/popupmenu.h \ + ./SourceFiles/ui/countryinput.h \ + ./SourceFiles/ui/emoji_config.h \ + ./SourceFiles/ui/filedialog.h \ + ./SourceFiles/ui/flatbutton.h \ + ./SourceFiles/ui/flatcheckbox.h \ + ./SourceFiles/ui/flatinput.h \ + ./SourceFiles/ui/flatlabel.h \ + ./SourceFiles/ui/flattextarea.h \ + ./SourceFiles/ui/images.h \ + ./SourceFiles/ui/inner_dropdown.h \ + ./SourceFiles/ui/scrollarea.h \ + ./SourceFiles/ui/twidget.h \ + ./SourceFiles/window/main_window.h \ + ./SourceFiles/window/section_memento.h \ + ./SourceFiles/window/section_widget.h \ + ./SourceFiles/window/slide_animation.h \ + ./SourceFiles/window/top_bar_widget.h win32 { SOURCES += \ - ./SourceFiles/pspecific_win.cpp \ - ./SourceFiles/platform/win/windows_app_user_model_id.cpp \ - ./SourceFiles/platform/win/windows_dlls.cpp \ - ./SourceFiles/platform/win/windows_event_filter.cpp \ - ./SourceFiles/platform/win/windows_toasts.cpp + ./SourceFiles/pspecific_win.cpp \ + ./SourceFiles/platform/win/windows_app_user_model_id.cpp \ + ./SourceFiles/platform/win/windows_dlls.cpp \ + ./SourceFiles/platform/win/windows_event_filter.cpp \ + ./SourceFiles/platform/win/windows_toasts.cpp HEADERS += \ - ./SourceFiles/pspecific_win.h \ - ./SourceFiles/platform/win/windows_app_user_model_id.h \ - ./SourceFiles/platform/win/windows_dlls.h \ - ./SourceFiles/platform/win/windows_event_filter.h \ - ./SourceFiles/platform/win/windows_toasts.h + ./SourceFiles/pspecific_win.h \ + ./SourceFiles/platform/win/windows_app_user_model_id.h \ + ./SourceFiles/platform/win/windows_dlls.h \ + ./SourceFiles/platform/win/windows_event_filter.h \ + ./SourceFiles/platform/win/windows_toasts.h } winrt { SOURCES += \ - ./SourceFiles/pspecific_winrt.cpp \ - ./SourceFiles/platform/winrt/main_window_winrt.cpp + ./SourceFiles/pspecific_winrt.cpp \ + ./SourceFiles/platform/winrt/main_window_winrt.cpp HEADERS += \ - ./SourceFiles/pspecific_winrt.h \ - ./Sourcefiles/platform/winrt/main_window_winrt.h + ./SourceFiles/pspecific_winrt.h \ + ./Sourcefiles/platform/winrt/main_window_winrt.h } macx { SOURCES += \ - ./SourceFiles/pspecific_mac.cpp + ./SourceFiles/pspecific_mac.cpp HEADERS += \ - ./SourceFiles/pspecific_mac.h + ./SourceFiles/pspecific_mac.h OBJECTIVE_SOURCES += \ - ./SourceFiles/pspecific_mac_p.mm \ - ./SourceFiles/platform/mac/main_window_mac.mm + ./SourceFiles/pspecific_mac_p.mm \ + ./SourceFiles/platform/mac/main_window_mac.mm HEADERS += \ - ./SourceFiles/pspecific_mac_p.h \ - ./SourceFiles/platform/mac/main_window_mac.h + ./SourceFiles/pspecific_mac_p.h \ + ./SourceFiles/platform/mac/main_window_mac.h } SOURCES += \ - ./ThirdParty/minizip/zip.c \ - ./ThirdParty/minizip/ioapi.c + ./ThirdParty/minizip/zip.c \ + ./ThirdParty/minizip/ioapi.c CONFIG += precompile_header @@ -450,19 +455,19 @@ QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-result -Wno-unused-parameter -Wno-unused-v QMAKE_CFLAGS_WARN_ON += -Wno-unused-result -Wno-unused-parameter -Wno-unused-variable -Wno-switch -Wno-comment -Wno-unused-but-set-variable CONFIG(release, debug|release) { - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -Ofast -flto -fno-strict-aliasing -g - QMAKE_LFLAGS_RELEASE -= -O1 - QMAKE_LFLAGS_RELEASE += -Ofast -flto -g -rdynamic -static-libstdc++ + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE += -Ofast -flto -fno-strict-aliasing -g + QMAKE_LFLAGS_RELEASE -= -O1 + QMAKE_LFLAGS_RELEASE += -Ofast -flto -g -rdynamic -static-libstdc++ } # Linux 32bit fails Release link with Link-Time Optimization: virtual memory exhausted unix { - !contains(QMAKE_TARGET.arch, x86_64) { - CONFIG(release, debug|release) { - QMAKE_CXXFLAGS_RELEASE -= -flto - QMAKE_LFLAGS_RELEASE -= -flto - } - } + !contains(QMAKE_TARGET.arch, x86_64) { + CONFIG(release, debug|release) { + QMAKE_CXXFLAGS_RELEASE -= -flto + QMAKE_LFLAGS_RELEASE -= -flto + } + } } CONFIG(debug, debug|release) { QMAKE_LFLAGS_DEBUG += -g -rdynamic -static-libstdc++ @@ -471,22 +476,23 @@ CONFIG(debug, debug|release) { include(qt_static.pri) INCLUDEPATH += \ - /usr/local/include\ - /usr/local/include/opus\ - ./SourceFiles\ - ./GeneratedFiles\ - ./ThirdParty/minizip\ - ./../../Libraries/breakpad/src + /usr/local/include\ + /usr/local/include/opus\ + ./SourceFiles\ + ./GeneratedFiles\ + ./ThirdParty/minizip\ + ./../../Libraries/breakpad/src INCLUDEPATH += "/usr/include/libappindicator-0.1" +#INCLUDEPATH += "/usr/include/gtk-3.0" INCLUDEPATH += "/usr/include/gtk-2.0" +INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include" +INCLUDEPATH += "/usr/lib/i386-linux-gnu/gtk-2.0/include" INCLUDEPATH += "/usr/include/glib-2.0" INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/glib-2.0/include" INCLUDEPATH += "/usr/lib/i386-linux-gnu/glib-2.0/include" INCLUDEPATH += "/usr/include/cairo" INCLUDEPATH += "/usr/include/pango-1.0" -INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include" -INCLUDEPATH += "/usr/lib/i386-linux-gnu/gtk-2.0/include" INCLUDEPATH += "/usr/include/gdk-pixbuf-2.0" INCLUDEPATH += "/usr/include/atk-1.0" @@ -502,21 +508,21 @@ LIBS += /usr/local/lib/libxkbcommon.a LIBS += ./../../../Libraries/breakpad/src/client/linux/libbreakpad_client.a RESOURCES += \ - ./Resources/telegram.qrc \ - ./Resources/telegram_linux.qrc \ - ./Resources/telegram_emojis.qrc + ./Resources/telegram.qrc \ + ./Resources/telegram_linux.qrc \ + ./Resources/telegram_emojis.qrc OTHER_FILES += \ - ./Resources/basic_types.style \ - ./Resources/basic.style \ - ./Resources/all_files.style \ - ./Resources/langs/lang.strings \ - ./Resources/langs/lang_it.strings \ - ./Resources/langs/lang_es.strings \ - ./Resources/langs/lang_de.strings \ - ./Resources/langs/lang_nl.strings \ - ./Resources/langs/lang_pt_BR.strings \ - ./SourceFiles/dialogs/dialogs.style \ - ./SourceFiles/history/history.style \ - ./SourceFiles/overview/overview.style \ - ./SourceFiles/profile/profile.style + ./Resources/basic_types.style \ + ./Resources/basic.style \ + ./Resources/all_files.style \ + ./Resources/langs/lang.strings \ + ./Resources/langs/lang_it.strings \ + ./Resources/langs/lang_es.strings \ + ./Resources/langs/lang_de.strings \ + ./Resources/langs/lang_nl.strings \ + ./Resources/langs/lang_pt_BR.strings \ + ./SourceFiles/dialogs/dialogs.style \ + ./SourceFiles/history/history.style \ + ./SourceFiles/overview/overview.style \ + ./SourceFiles/profile/profile.style diff --git a/Telegram/qt_static.pri b/Telegram/qt_static.pri index 9873c80adf..4cbcf7b5e8 100644 --- a/Telegram/qt_static.pri +++ b/Telegram/qt_static.pri @@ -1,20 +1,26 @@ QT_TDESKTOP_VERSION_DEFAULT = 5.6.0 QT_TDESKTOP_PATH_DEFAULT = /usr/local/tdesktop/Qt-$${QT_TDESKTOP_VERSION_DEFAULT} -QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION} QT_TDESKTOP_PATH = $${QT_TDESKTOP_PATH} - isEmpty(QT_TDESKTOP_PATH) { - message(QT_TDESKTOP_PATH is not set. Using default value $${QT_TDESKTOP_PATH_DEFAULT}) - QT_TDESKTOP_PATH = $${QT_TDESKTOP_PATH_DEFAULT} - + QT_TDESKTOP_PATH = $$(QT_TDESKTOP_PATH) + isEmpty(QT_TDESKTOP_PATH) { + message(QT_TDESKTOP_PATH is not set. Using default value $${QT_TDESKTOP_PATH_DEFAULT}) + QT_TDESKTOP_PATH = $${QT_TDESKTOP_PATH_DEFAULT} + } } + +QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION} isEmpty(QT_TDESKTOP_VERSION) { - message(QT_TDESKTOP_VERSION is not set. Using default value $${QT_TDESKTOP_VERSION_DEFAULT}) - QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION_DEFAULT} + QT_TDESKTOP_VERSION = $$(QT_TDESKTOP_VERSION) + isEmpty(QT_TDESKTOP_VERSION) { + message(QT_TDESKTOP_VERSION is not set. Using default value $${QT_TDESKTOP_VERSION_DEFAULT}) + QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION_DEFAULT} + } } INCLUDEPATH += $${QT_TDESKTOP_PATH}/include/QtGui/$${QT_TDESKTOP_VERSION}/QtGui \ $${QT_TDESKTOP_PATH}/include/QtCore/$${QT_TDESKTOP_VERSION}/QtCore \ + $${QT_TDESKTOP_PATH}/include/QtCore/$${QT_TDESKTOP_VERSION} \ $${QT_TDESKTOP_PATH}/include diff --git a/doc/building-msvc.md b/doc/building-msvc.md index f07e8be9ff..58865d87e5 100644 --- a/doc/building-msvc.md +++ b/doc/building-msvc.md @@ -1,10 +1,36 @@ -##Build instructions for Visual Studio 2015 +# Build instructions for Visual Studio 2015 -###Prepare folder + * [Prepare folder](#prepare-folder) + * [Clone source code](#clone-source-code) + * [Prepare libraries](#prepare-libraries) + + [OpenSSL](#openssl) + + [LZMA SDK 9.20](#lzma-sdk-920) + - [Building library](#building-library) + + [zlib 1.2.8](#zlib-128) + - [Building library](#building-library-1) + + [libexif 0.6.20](#libexif-0620) + - [Building library](#building-library-2) + + [OpenAL Soft, slightly patched](#openal-soft-slightly-patched) + - [Building library](#building-library-3) + + [Opus codec](#opus-codec) + - [Building libraries](#building-libraries) + + [FFmpeg](#ffmpeg) + - [Building libraries](#building-libraries-1) + + [Qt 5.6.0, slightly patched](#qt-560-slightly-patched) + - [Apply the patch](#apply-the-patch) + - [Install Windows SDKs](#install-windows-sdks) + - [Building library](#building-library-4) + + [Qt5Package](#qt5package) + + [Google Breakpad](#google-breakpad) + - [Install](#install) + - [Build](#build) + * [Building Telegram Desktop](#building-telegram-desktop) + +## Prepare folder Choose a folder for the future build, for example **D:\TBuild\**. There you will have two folders, **Libraries** for third-party libs and **tdesktop** (or **tdesktop-master**) for the app. -###Clone source code +## Clone source code By git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild** and run @@ -12,9 +38,9 @@ By git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild** and r or download in ZIP and extract to **D:\TBuild\**, rename **tdesktop-master** to **tdesktop** to have **D:\TBuild\tdesktop\Telegram.sln** solution -###Prepare libraries +## Prepare libraries -####OpenSSL +### OpenSSL Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder), go to **D:\\TBuild\\Libraries** and run @@ -35,13 +61,13 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > nmake -f ms\nt.mak install -####LZMA SDK 9.20 +### LZMA SDK 9.20 http://www.7-zip.org/sdk.html > Download [**LZMA SDK (C, C++, C#, Java)** 9.20](http://downloads.sourceforge.net/sevenzip/lzma920.tar.bz2) Extract to **D:\TBuild\Libraries** -#####Building library +#### Building library * Open in VS2015 **D:\TBuild\Libraries\lzma\C\Util\LzmaLib\LzmaLib.dsw** > One-way upgrade – **OK** * For **Debug** and **Release** configurations @@ -53,13 +79,13 @@ Extract to **D:\TBuild\Libraries** * Build Debug configuration * Build Release configuration -####zlib 1.2.8 +### zlib 1.2.8 http://www.zlib.net/ > Download [**zlib source code, version 1.2.8, zipfile format**](http://zlib.net/zlib128.zip) Extract to **D:\\TBuild\\Libraries\\** -#####Building library +#### Building library * Open in VS2015 **D:\TBuild\Libraries\zlib-1.2.8\contrib\vstudio\vc11\zlibvc.sln** > One-way upgrade – **OK** * We are interested only in **zlibstat** project, but it depends on some custom pre-build step, so build all @@ -70,7 +96,7 @@ Extract to **D:\\TBuild\\Libraries\\** * Build Solution for Debug configuration – only **zlibstat** project builds successfully * Build Solution for Release configuration – only **zlibstat** project builds successfully -####libexif 0.6.20 +### libexif 0.6.20 Get sources from https://github.com/telegramdesktop/libexif-0.6.20, by git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild/libraries** and run @@ -78,13 +104,13 @@ Get sources from https://github.com/telegramdesktop/libexif-0.6.20, by git – i or download in ZIP and extract to **D:\TBuild\Libraries\**, rename **libexif-0.6.20-master** to **libexif-0.6.20** to have **D:\TBuild\Libraries\libexif-0.6.20\win32\lib_exif.sln** solution -#####Building library +#### Building library * Open in VS2015 **D:\TBuild\Libraries\libexif-0.6.20\win32\lib_exif.sln** * Build Debug configuration * Build Release configuration -####OpenAL Soft, slightly patched +### OpenAL Soft, slightly patched Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder), go to **D:\\TBuild\\Libraries** and run @@ -93,7 +119,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > git checkout 90349b38 git apply ./../../tdesktop/Telegram/Patches/openal.diff -#####Building library +#### Building library * Install [CMake](http://www.cmake.org/) * Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder), go to **D:\TBuild\Libraries\openal-soft\build\** and run @@ -102,7 +128,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > * Open in VS2015 **D:\TBuild\Libraries\openal-soft\build\OpenAL.sln** and build Debug and Release configurations -####Opus codec +### Opus codec Get sources by git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild/libraries** and run @@ -110,13 +136,13 @@ Get sources by git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tb to have **D:\TBuild\Libraries\opus\win32** -#####Building libraries +#### Building libraries * Open in VS2015 **D:\TBuild\Libraries\opus\win32\VS2010\opus.sln** * Build Debug configuration * Build Release configuration (it will be required in **FFmpeg** build!) -####FFmpeg +### FFmpeg Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder) and run @@ -126,7 +152,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > http://msys2.github.io/ > Download [msys2-x86_64-20150512.exe](http://sourceforge.net/projects/msys2/files/Base/x86_64/msys2-x86_64-20150512.exe/download) and install to **D:\\msys64** -#####Building libraries +#### Building libraries Download [yasm for Win64](http://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win64.exe) from http://yasm.tortall.net/Download.html, rename **yasm-1.3.0-win64.exe** to **yasm.exe** and place it to your Visual C++ **bin** directory, like **\\Program Files (x86)\\Microsoft Visual Studio 14\\VC\\bin\\** @@ -148,7 +174,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > make make install -####Qt 5.6.0, slightly patched +### Qt 5.6.0, slightly patched * Install Python 3.3.2 from https://www.python.org/download/releases/3.3.2 > [**Windows x86 MSI Installer (3.3.2)**](https://www.python.org/ftp/python/3.3.2/python-3.3.2.msi) * Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder) @@ -168,17 +194,17 @@ and run cd qtimageformats && git checkout v5.6.0 && cd .. cd qtbase && git checkout v5.6.0 && cd .. -#####Apply the patch +#### Apply the patch cd qtbase && git apply ../../../tdesktop/Telegram/Patches/qtbase_5_6_0.diff && cd .. -#####Install Windows SDKs +#### Install Windows SDKs If you didn't install Windows SDKs before, you need to install them now. To install the SDKs just open Telegram solution at **D:\TBuild\tdesktop\Telegram.sln** and on startup Visual Studio 2015 will popup dialog box and ask to download and install extra components (including Windows 7 SDK). If you already have Windows SDKs then find the library folder and correct it at configure's command below (like **C:\Program Files (x86)\Windows Kits\8.0\Lib\win8\um\x86**). -#####Building library +#### Building library configure -debug-and-release -force-debug-info -opensource -confirm-license -static -I "D:\TBuild\Libraries\openssl\Release\include" -L "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib" -l Gdi32 -no-opengl -openssl-linked OPENSSL_LIBS_DEBUG="D:\TBuild\Libraries\openssl_debug\Debug\lib\ssleay32.lib D:\TBuild\Libraries\openssl_debug\Debug\lib\libeay32.lib" OPENSSL_LIBS_RELEASE="D:\TBuild\Libraries\openssl\Release\lib\ssleay32.lib D:\TBuild\Libraries\openssl\Release\lib\libeay32.lib" -mp -nomake examples -nomake tests -platform win32-msvc2015 nmake @@ -186,15 +212,19 @@ If you already have Windows SDKs then find the library folder and correct it at building (**nmake** command) will take really long time. -####Qt5Package +### Qt5Package https://visualstudiogallery.msdn.microsoft.com/c89ff880-8509-47a4-a262-e4fa07168408 Download, close all VS2015 instances and install for VS2015 -####Google Breakpad +### Google Breakpad -* Install Python 2.7.11 from https://www.python.org/downloads/release/python-2711/ > [**Windows x86 MSI installer**](https://www.python.org/ftp/python/2.7.11/python-2.7.11.msi) +Breakpad is a set of client and server components which implement a crash-reporting system. + +#### Install + +* Install Python 2.7.12 from https://www.python.org/downloads/release/python-2712/ > [**Windows x86 MSI installer**](https://www.python.org/ftp/python/2.7.12/python-2.7.12.msi). Make sure that python is added to your `PATH` (there is an option for this in the python installer). * Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder) There go to Libraries directory @@ -204,19 +234,18 @@ There go to Libraries directory and run - set PATH=C:\Python27;%PATH% git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git cd depot_tools + gclient config "https://chromium.googlesource.com/breakpad/breakpad.git" gclient sync cd .. - md breakpad - cd breakpad + md breakpad && cd breakpad ..\depot_tools\fetch breakpad ..\depot_tools\gclient sync + xcopy src\src\* src /s /i -There's now a src folder within a src folder: D:\TBuild\Libraries\breakpad\src\src. Telegram only expects one src folder. Either via the command line or File Explorer, rename the top-level src folder and move the inner src folder one level up. This way, what was once breakpad\src\src\client is now breakpad\src\client, etc. -#####Building library +#### Build * Open in VS2015 **D:\TBuild\Libraries\breakpad\src\client\windows\breakpad_client.sln** * Change "Treat WChar_t As Built in Type" to "No" in all projects & configurations @@ -224,7 +253,7 @@ There's now a src folder within a src folder: D:\TBuild\Libraries\breakpad\src\s * Build Debug configuration * Build Release configuration -###Building Telegram Desktop +## Building Telegram Desktop * Launch VS2015 for configuring Qt5Package * QT5 > Qt Options > Add diff --git a/doc/building-qmake.md b/doc/building-qmake.md index 55bf8c53be..ffeb1832be 100644 --- a/doc/building-qmake.md +++ b/doc/building-qmake.md @@ -72,7 +72,7 @@ Building cd "$srcdir/Libraries/QtStatic" ./configure -prefix "$srcdir/qt" -release -opensource -confirm-license -qt-zlib \ -qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb \ - -qt-xkbcommon-x11 -no-opengl -static -nomake examples -nomake tests + -qt-xkbcommon-x11 -no-opengl -no-gtkstyle -static -nomake examples -nomake tests make module-qtbase module-qtimageformats make module-qtbase-install_subtargets module-qtimageformats-install_subtargets diff --git a/doc/building-qtcreator.md b/doc/building-qtcreator.md index eb605ed15c..18695f1284 100644 --- a/doc/building-qtcreator.md +++ b/doc/building-qtcreator.md @@ -147,7 +147,7 @@ Install some packages for Qt (see **/home/user/TBuild/Libraries/qt5_6_0/qtbase/s In Terminal go to **/home/user/TBuild/Libraries/qt5_6_0** and there run - OPENSSL_LIBS='-L/usr/local/ssl/lib -lssl -lcrypto' ./configure -prefix "/usr/local/tdesktop/Qt-5.6.0" -release -force-debug-info -opensource -confirm-license -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb -qt-xkbcommon-x11 -no-opengl -static -openssl-linked -nomake examples -nomake tests + OPENSSL_LIBS='-L/usr/local/ssl/lib -lssl -lcrypto' ./configure -prefix "/usr/local/tdesktop/Qt-5.6.0" -release -force-debug-info -opensource -confirm-license -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb -qt-xkbcommon-x11 -no-opengl -no-gtkstyle -static -openssl-linked -nomake examples -nomake tests make -j4 sudo make install